Uber永久定位系統實時資料分析過程實踐!

趙鈺瑩發表於2018-08-20

根據Gartner所言,到2020年,每個智慧城市將使用約13.9億輛聯網汽車,這些汽車配備物聯網感測器和其他裝置。城市中的車輛定位和行為模式分析將有助於最佳化流量,更好的規劃決策和進行更智慧的廣告投放。例如,對GPS汽車資料分析可以允許城市基於實時交通訊息來最佳化交通流量。電信公司正在使用行動電話定位資料,識別和預測城市人口的位置活動趨勢和生存區域。

本文,我們將討論在資料處理管道中使用Spark Structured Streaming對Uber事件資料進行聚類分析,以檢測和視覺化使用者位置實踐。(注:本文所用資料並非Uber內部實際使用者資料,文末附具體程式碼或者示例獲取渠道)

首先,我們回顧幾個結構化流媒體涉及的概念,然後探討端到端用例:

  • 使用MapR-ES釋出/訂閱事件流

  • MapR-ES是一個分散式釋出/訂閱事件流系統,讓生產者和消費者能夠透過Apache Kafka API以並行和容錯方式實時交換事件。

  • 流表示從生產者到消費者的連續事件序列,其中事件被定義為鍵值對。

  • topic是一個邏輯事件流,將事件按類別區分,並將生產者與消費者分離。topic按吞吐量和可伸縮性進行分割槽,MapR-ES可以擴充套件到非常高的吞吐量級別,使用普通硬體可以輕鬆實現每秒傳輸數百萬條訊息。

你可以將分割槽視為事件日誌:將新事件附加到末尾,併為其分配一個稱為偏移的順序ID號。

與佇列一樣,事件按接收順序傳遞。

但是,與佇列不同,訊息在讀取時不會被刪除,它們保留在其他消費者可用分割槽。訊息一旦釋出,就不可變且永久保留。

讀取訊息時不刪除訊息保證了大規模讀取時的高效能,滿足不同消費者針對不同目的(例如具有多語言永續性的多個檢視)處理相同訊息的需求。

Spark資料集,DataFrame,SQL

Spark資料集是分佈在叢集多個節點上類物件的分散式集合,可以使用map,flatMap,filter或Spark SQL來操縱資料集。DataFrame是Row物件的資料集,表示包含行和列的資料表。

Spark結構化流

結構化流是一種基於Spark SQL引擎的可擴充套件、可容錯的流處理引擎。透過Structured Streaming,你可以將釋出到Kafka的資料視為無界DataFrame,並使用與批處理相同的DataFrame,Dataset和SQL API處理此資料。

隨著流資料的不斷傳播,Spark SQL引擎會逐步持續處理並更新最終結果。

事件的流處理對實時ETL、過濾、轉換、建立計數器、聚合、關聯值、豐富其他資料來源或機器學習、持久化檔案或資料庫以及釋出到管道的不同topic非常有用。

Spark結構化流示例程式碼

下面是Uber事件資料聚類分析用例的資料處理管道,用於檢測位置。

  1. 使用Kafka API將行車位置資料釋出到MapR-ES topic

  2. 訂閱該topic的Spark Streaming應用程式:

  • 輸入Uber行車資料流;

  • 使用已部署的機器學習模型、叢集ID和位置豐富行程資料;

  • 在MapR-DB JSON中儲存轉換和豐富資料。

 

用例資料示例

示例資料集是Uber旅行資料,傳入資料是CSV格式,下面顯示了一個示例,topic依次為:

日期/時間,緯度,經度,位置(base),反向時間戳

2014-08-06T05:29:00.000-07:00,40.7276,-74.0033,B02682,9223370505593280605

我們使用叢集ID和位置豐富此資料,然後將其轉換為以下JSON物件:

{  
"_id":0_922337050559328,
"dt":"2014-08-01 08:51:00",
"lat":40.6858,
"lon":-73.9923,
"base":"B02682",
"cid":0,
"clat":40.67462874550765,
"clon":-73.98667466026531  
}

載入K-Means模型

Spark KMeansModel類用於載入k-means模型,該模型安裝在歷史uber行程資料上,然後儲存到MapR-XD叢集。接下來,建立叢集中心ID和位置資料集,以便稍後與Uber旅行位置連線。

叢集中心下方顯示在Zeppelin notebook中的Google地圖上:

從Kafka的topic中讀取資料

為了從Kafka讀取,我們必須首先指定流格式,topic和偏移選項。有關配置引數的詳細資訊,請參閱MapR Streams文件。

這將返回具有以下架構的DataFrame:

下一步是將二進位制值列解析並轉換為Uber物件的資料集。

將訊息值解析為Uber物件的資料集

Scala Uber案例類定義與CSV記錄對應的架構,parseUber函式將逗號分隔值字串解析為Uber物件。

在下面的程式碼中,我們使用parseUber函式註冊一個使用者自定義函式(UDF)來反序列化訊息值字串。我們在帶有df1列值的String Cast的select表示式中使用UDF,該值返回Uber物件的DataFrame。

使用叢集中心ID和位置豐富的Uber物件資料集

VectorAssembler用於轉換並返回一個新的DataFrame,其中包含向量列中的緯度和經度要素列。


k-means模型用於透過模型轉換方法從特徵中獲取聚類,該方法返回具有聚類ID(標記為預測)的DataFrame。生成的資料集與先前建立的叢集中心資料集(ccdf)連線,以建立UberC物件的資料集,其中包含與叢集中心ID和位置相結合的行程資訊。

最後的資料集轉換是將唯一ID新增到物件以儲存在MapR-DB JSON中。createUberwId函式建立一個唯一的ID,包含叢集ID和反向時間戳。由於MapR-DB按id對行進行分割槽和排序,因此行將按簇的ID新舊時間進行排序。 此函式與map一起使用以建立UberwId物件的資料集。

寫入記憶體接收器

接下來,為了進行除錯,我們可以開始接收資料並將資料作為記憶體表儲存在記憶體中,然後進行查詢。

以下是來自  %sqlselect * from uber limit 10 的示例輸出:

現在我們可以查詢流資料,詢問哪段時間和叢集內的搭乘次數最多?(輸出顯示在Zeppelin notebook中)

%sql
SELECT hour(uber.dt) as hr,cid, count(cid) as ct FROM uber group By hour(uber.dt), cid

Spark Streaming寫入MapR-DB

用於Apache Spark的MapR-DB聯結器使使用者可以將MapR-DB用作Spark結構化流或Spark Streaming的接收器。

當你處理大量流資料時,其中一個挑戰是儲存位置。對於此應用程式,可以選擇MapR-DB JSON(一種高效能NoSQL資料庫),因為它具有JSON的可伸縮性和靈活易用性。

JSON模式的靈活性

MapR-DB支援JSON文件作為本機資料儲存。MapR-DB使用JSON文件輕鬆儲存,查詢和構建應用程式。Spark聯結器可以輕鬆地在JSON資料和MapR-DB之間構建實時或批處理管道,並在管道中利用Spark。

使用MapR-DB,表按叢集的鍵範圍自動分割槽,提供可擴充套件行和快速讀寫能力。在此用例中,行鍵_id由叢集ID和反向時間戳組成,因此表將自動分割槽,並按最新的叢集ID進行排序。

Spark MapR-DB Connector利用Spark DataSource API。聯結器體系結構在每個Spark Executor中都有一個連線物件,允許使用MapR-DB(分割槽)進行分散式並行寫入,讀取或掃描。

寫入MapR-DB接收器

要將Spark Stream寫入MapR-DB,請使用tablePath,idFieldPath,createTable,bulkMode和sampleSize引數指定格式。以下示例將cdf DataFrame寫到MapR-DB並啟動流。


使用Spark SQL查詢MapR-DB JSON

Spark MapR-DB Connector允許使用者使用Spark資料集在MapR-DB之上執行復雜的SQL查詢和更新,同時應用投影和過濾器下推,自定義分割槽和資料位置等關鍵技術。


將資料從MapR-DB載入到Spark資料集中

要將MapR-DB JSON表中的資料載入到Apache Spark資料集,我們可在SparkSession物件上呼叫loadFromMapRDB方法,提供tableName,schema和case類。這將返回UberwId物件的資料集:

使用Spark SQL探索和查詢Uber資料

現在,我們可以查詢連續流入MapR-DB的資料,使用Spark DataFrames特定於域的語言或使用Spark SQL來詢問。

顯示第一行(注意行如何按_id分割槽和排序,_id由叢集ID和反向時間戳組成,反向時間戳首先排序最近的行)。

df.show

每個叢集發生多少次搭乘?

df.groupBy("cid").count().orderBy(desc( "count")).show

或者使用Spark SQL:

%sql SELECT COUNT(cid), cid FROM uber GROUP BY cid ORDER BY COUNT(cid) DESC

使用Zeppelin notebook中的Angular和Google Maps指令碼,我們可以在地圖上顯示叢集中心標記和最新的5000個旅行的位置,如下可看出最受歡迎的位置,比如位於曼哈頓的0、3、9。

叢集0最高搭乘次數出現在哪個小時?

df.filter($"\_id" <= "1")
  .select(hour($"dt").alias("hour"), $"cid")
  .groupBy("hour","cid").agg(count("cid")
  .alias("count"))show

一天中的哪個小時和哪個叢集的搭乘次數最多?

%sql SELECT hour(uber.dt), cid, count(cid) FROM uber GROUP BY hour(uber.dt), cid

按日期時間顯示uber行程的叢集計數

%sql select cid, dt, count(cid) as count from uber group by dt, cid order by dt, cid limit 100

總結

本文涉及的知識點有Spark結構化流應用程式中的Spark Machine Learning模型、Spark結構化流與MapR-ES使用Kafka API攝取訊息、SparkStructured Streaming持久化儲存到MapR-DB,以持續快速地進行SQL分析等。此外,上述討論過的用例體系結構所有元件都可與MapR資料平臺在同一叢集上執行。

程式碼:

  • 你可以從此處下載程式碼和資料以執行這些示例:https://github.com/caroljmcdonald/mapr-spark-structuredstreaming-uber

  • 機器學習notebook的Zeppelin檢視器:https://

  • Spark結構化流notebook的Zeppelin檢視器:https://

  • SparkSQL notebook的Zenpelin檢視器:https://

  • 此程式碼包含在MapR 6.0.1沙箱上執行的說明,這是一個獨立的VM以及教程和演示應用程式,可讓使用者快速使用MapR和Spark。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31077337/viewspace-2212401/,如需轉載,請註明出處,否則將追究法律責任。

相關文章