1. 程式人生 > >Spark流處理中的DStrem.foreachRDD()方法

Spark流處理中的DStrem.foreachRDD()方法

Spark資料處理

Spark作為分散式資料處理的一個開源框架,因其計算的高效性和簡潔的API而廣受歡迎。一般來說,Spark大部分時候被用來進行批處理。但現在Spark通過其SparkStreaming模組也實現了一定的流處理的功能。

Spark流處理的過程

Spark中的流處理實際上並不是真正的流處理。Spark實現流處理的方法是通過mini-batch來對輸入資料進行分塊(但這個分塊頻率非常高以至於能夠模擬流處理的過程)。 在進行mini-batch分塊的時候,Spark引入了DStream的概念。

所謂的DStream,或者說Discretized Stream指的是將連續的流資料分成小塊批資料的抽象。這就是我們上面說的mini-batch

過程。每一個mini-batch體現為一個所謂的RDD(Resilient Distributed Dataset)。而RDD被 交給Spark executor進行進一步的處理。對每一個mini-batch間隔對應的DStream來說,有且僅有一個RDD被產生。

一個RDD是一份分散式的資料集。我們可以把RDD當成指向叢集中真正資料塊的指標。

DStream.foreachRDD()方法實際上是Spark流處理的一個處理及輸出RDD的方法。這個方法使我們能夠訪問底層的DStream對應的RDD進而根據我們需要的邏輯對其進行處理。例如,我們可以通過foreachRDD()方法來訪問每一條mini-batch

中的資料,然後將它們存入資料庫。

這裡需要注意的一點是DStream實際上是一組根據時間被分割出來的資料集合。這裡我們可以通過如下兩段程式來對比傳統的集合和Spark中的時序集合DStream的區別。

userList = [something...]
userList.foreach(lambda user:doSomething(user))

這段程式將會對userList集合中的每一個元素執行doSomething()函式。

在流處理問題中,我們所面對的不同情況是我們提前並不知道所有的元素。因此我們無法將它們都放入一個list中。相反的,我們對於流中的每一個元素執行某種操作,就好像意見飯店不斷服務前來吃飯的客人一樣。

# A DStream of user
userDStream = ???

# For each RDD batch, process each element in it
userDStream.foreachRDD(lambda userbatch:userbatch.foreach(doSomeThing(user)))

需要注意的是:

  • DStream.foreachRDD()傳給我們的引數是一個RDD[userbatch],而不是單個的user。用上面飯店的例子來講,我們得到的不是一個單個的客人,而是某一個時間段內到來的一波客人。因此我們需要進一步迴圈來根據需要處理其中每一個user
  • 我們不能用傳統的for ele in iterable方法來迴圈其中的元素。因此我們需要用rdd.foreach()來分別處理其中每一個user

進一步分析Spark的流處理過程:我們擁有幾個Spark的executor。對於穩定到來的資料流,Spark Streaming負責根據一定的時間間隔將流輸入分成小的資料塊(batch),然後Spark將這些小資料塊(mini-batch)分配給不同的executor,就像飯店將不同的顧客分配給不同的服務員一樣。通過這樣的操作,Spark實現了並行的資料計算,從而加速了資料處理的速度。