Spark數(shù)據(jù)處理
Spark作為分布式數(shù)據(jù)處理的一個(gè)開源框架,因其計(jì)算的高效性和簡(jiǎn)潔的API而廣受歡迎。一般來(lái)說(shuō),Spark大部分時(shí)候被用來(lái)進(jìn)行批處理。但現(xiàn)在Spark通過(guò)其SparkStreaming模塊也實(shí)現(xiàn)了一定的流處理的功能。
Spark流處理的過(guò)程
Spark中的流處理實(shí)際上并不是真正的流處理。Spark實(shí)現(xiàn)流處理的方法是通過(guò)mini-batch來(lái)對(duì)輸入數(shù)據(jù)進(jìn)行分塊(但這個(gè)分塊頻率非常高以至于能夠模擬流處理的過(guò)程)。 在進(jìn)行mini-batch分塊的時(shí)候,Spark引入了DStream的概念。
所謂的DStream
,或者說(shuō)Discretized Stream
指的是將連續(xù)的流數(shù)據(jù)分成小塊批數(shù)據(jù)的抽象。這就是我們上面說(shuō)的mini-batch過(guò)程。每一個(gè)mini-batch體現(xiàn)為一個(gè)所謂的RDD(Resilient Distributed Dataset)。而RDD被 交給Spark executor進(jìn)行進(jìn)一步的處理。對(duì)每一個(gè)mini-batch間隔對(duì)應(yīng)的DStream來(lái)說(shuō),有且僅有一個(gè)RDD被產(chǎn)生。
一個(gè)RDD是一份分布式的數(shù)據(jù)集。我們可以把RDD當(dāng)成指向集群中真正數(shù)據(jù)塊的指針。
DStream.foreachRDD()
方法實(shí)際上是Spark流處理的一個(gè)處理及輸出RDD的方法。這個(gè)方法使我們能夠訪問(wèn)底層的DStream對(duì)應(yīng)的RDD進(jìn)而根據(jù)我們需要的邏輯對(duì)其進(jìn)行處理。例如,我們可以通過(guò)foreachRDD()
方法來(lái)訪問(wèn)每一條mini-batch中的數(shù)據(jù),然后將它們存入數(shù)據(jù)庫(kù)。
這里需要注意的一點(diǎn)是DStream實(shí)際上是一組根據(jù)時(shí)間被分割出來(lái)的數(shù)據(jù)集合。這里我們可以通過(guò)如下兩段程序來(lái)對(duì)比傳統(tǒng)的集合和Spark中的時(shí)序集合DStream的區(qū)別。
userList = [something...]
userList.foreach(lambda user:doSomething(user))
這段程序?qū)?huì)對(duì)userList
集合中的每一個(gè)元素執(zhí)行doSomething()
函數(shù)。
在流處理問(wèn)題中,我們所面對(duì)的不同情況是我們提前并不知道所有的元素。因此我們無(wú)法將它們都放入一個(gè)list
中。相反的,我們對(duì)于流中的每一個(gè)元素執(zhí)行某種操作,就好像意見飯店不斷服務(wù)前來(lái)吃飯的客人一樣。
# A DStream of user
userDStream = ???
# For each RDD batch, process each element in it
userDStream.foreachRDD(lambda userbatch:userbatch.foreach(doSomeThing(user)))
需要注意的是:
-
DStream.foreachRDD()
傳給我們的參數(shù)是一個(gè)RDD[userbatch]
,而不是單個(gè)的user。用上面飯店的例子來(lái)講,我們得到的不是一個(gè)單個(gè)的客人,而是某一個(gè)時(shí)間段內(nèi)到來(lái)的一波客人。因此我們需要進(jìn)一步循環(huán)來(lái)根據(jù)需要處理其中每一個(gè)user
。 - 我們不能用傳統(tǒng)的
for ele in iterable
方法來(lái)循環(huán)其中的元素。因此我們需要用rdd.foreach()
來(lái)分別處理其中每一個(gè)user
。
進(jìn)一步分析Spark的流處理過(guò)程:我們擁有幾個(gè)Spark的executor。對(duì)于穩(wěn)定到來(lái)的數(shù)據(jù)流,Spark Streaming負(fù)責(zé)根據(jù)一定的時(shí)間間隔將流輸入分成小的數(shù)據(jù)塊(batch),然后Spark將這些小數(shù)據(jù)塊(mini-batch)分配給不同的executor,就像飯店將不同的顧客分配給不同的服務(wù)員一樣。通過(guò)這樣的操作,Spark實(shí)現(xiàn)了并行的數(shù)據(jù)計(jì)算,從而加速了數(shù)據(jù)處理的速度。