技術(shù)背景
- Spark Streaming會接收實時數(shù)據(jù)源的數(shù)據(jù),并切分成很多小的batches,然后被Spark Engine執(zhí)行,產(chǎn)出同樣由很多小的batchs組成的結(jié)果流。本質(zhì)上,這是一種micro-batch(微批處理)的方式處理,用批的思想去處理流數(shù)據(jù).這種設(shè)計讓Spark Streaming面對復(fù)雜的流式處理場景時捉襟見肘。
- spark streaming這種構(gòu)建在微批處理上的流計算引擎,比較突出的問題就是處理延時較高(無法優(yōu)化到秒以下的數(shù)量級),以及無法支持基于event_time的時間窗口做聚合邏輯。
- 在這段時間,流式計算一直沒有一套標(biāo)準(zhǔn)化、能應(yīng)對各種場景的模型,直到2015年google發(fā)表了The Dataflow Model的論文
設(shè)計目的
解決真實時計算場景,基于事件計算
設(shè)計思想
對無邊界,無序的數(shù)據(jù)源,允許按數(shù)據(jù)本身的特征進(jìn)行窗口計算,得到基于事件發(fā)生時間的有序結(jié)果,并能在準(zhǔn)確性、延遲程度和處理成本之間調(diào)整。
將實時到達(dá)的數(shù)據(jù)看作是一個不斷追加的unbound table無界表,到達(dá)流的每個數(shù)據(jù)項(RDD)就像是表中的一個新行被附加到無邊界的表中
技術(shù)本質(zhì)
一個流的數(shù)據(jù)源從邏輯上來說就是一個不斷增長的動態(tài)表格,隨著時間的推移,新數(shù)據(jù)被持續(xù)不斷地添加到表格的末尾。
核心特性
- 簡潔的模型;用戶可以直接把一個流看做是一個無限增長的表格
- 一致的API; Structured Stream 和SparkSql共用大部分API,
- 卓越的性能; Structured Stream也直接使用了SparkSQL的Catalyst優(yōu)化器和Tungsten,數(shù)據(jù)處理性能十分出色
- 多語言支持; scala,java,python,R,sql
DataFlow模型
- 背景:
作為數(shù)據(jù)工作者,不能把無邊界數(shù)據(jù)集(數(shù)據(jù)流)切分成有邊界的數(shù)據(jù),等待一個批次完整后處理。相反地,應(yīng)該假設(shè)永遠(yuǎn)無法知道數(shù)據(jù)流是否終結(jié),何時數(shù)據(jù)會變完整。唯一確信的是,新的數(shù)據(jù)會源源不斷而來,老的數(shù)據(jù)可能會被撤銷或更新。 - 概念:
一種基于事件的流式處理數(shù)據(jù)的思想 - 思想:
對無邊界,無序的數(shù)據(jù)源,允許按數(shù)據(jù)本身的特征進(jìn)行窗口計算,得到基于事件發(fā)生時間的有序結(jié)果,并能在準(zhǔn)確性、延遲程度和處理成本之間調(diào)整。 - 內(nèi)容:
- 基于事件時間的計算: 真實時計算,產(chǎn)生一條處理一條,flink,storm
- Event_time: 事件時間,一般在數(shù)據(jù)產(chǎn)生時記錄
- Process_time: 處理時間,事件開始處理的時間
- ingest_time: 到達(dá)時間
- 基于窗口的計算: 準(zhǔn)實時計算,微批處理,spark stream
- fixed window: 固定窗口,窗口間隔等于窗口長度
- sliding window: 滑動窗口,窗口間隔不等于窗口長度,容易造成數(shù)據(jù)丟失或數(shù)據(jù)重復(fù)
- sessions: 以某一事件作為窗口起始,通常以時間定義窗口大?。ㄒ灿锌赡苁鞘录螖?shù)),發(fā)生在超時時間以內(nèi)的事件都屬于同一會話
- 基于事件時間的計算: 真實時計算,產(chǎn)生一條處理一條,flink,storm
Structured Stream
概念:
Structured Streaming是一個基于Spark SQL引擎的可擴(kuò)展、容錯的流處理引擎。統(tǒng)一了流、批的編程模型,你可以使用靜態(tài)數(shù)據(jù)批處理一樣的方式來編寫流式計算操作。并且支持基于event_time的時間窗口的處理邏輯。-
內(nèi)容:
- 隨著數(shù)據(jù)不斷地到達(dá),Spark 引擎會以一種增量的方式來執(zhí)行這些操作,并且持續(xù)更新結(jié)算結(jié)果。
- Structured Streaming會通過checkpoint和預(yù)寫日志等機(jī)制來實現(xiàn)Exactly-Once語義。
- 結(jié)構(gòu)化流式查詢使用微批處理引擎進(jìn)行處理,該引擎將數(shù)據(jù)流作為一系列小批處理作業(yè)進(jìn)行處理,從而實現(xiàn)端到端的延遲,最短可達(dá)100毫秒,并且完全可以保證一次容錯。自Spark 2.3以來,引入了一種新的低延遲處理模式,稱為連續(xù)處理,它可以在至少一次保證的情況下實現(xiàn)低至1毫秒的端到端延遲。也就是類似于 Flink 那樣的實時流,而不是小批量處理。實際開發(fā)可以根據(jù)應(yīng)用程序要求選擇處理模式,但是連續(xù)處理在使用的時候仍然有很多限制,目前大部分情況還是應(yīng)該采用小批量模式。
-
對比:
- Spark Streaming 采用的數(shù)據(jù)抽象是DStream,而本質(zhì)上就是時間上連續(xù)的RDD,對數(shù)據(jù)流的操作就是針對RDD的操作
- Structured Streaming是Spark2.0新增的可擴(kuò)展和高容錯性的實時計算框架,它構(gòu)建于Spark SQL引擎,把流式計算也統(tǒng)一到DataFrame/Dataset里去了。Structured Streaming 相比于 Spark Streaming 的進(jìn)步就類似于 Dataset 相比于 RDD 的進(jìn)步,最主要的一個原因就是希望用戶不再需要分別為批處理和流處理編寫不同代碼,而是直接使用同一套代碼。不過需要注意的是盡管在2.2.0以后 Structured Streaming 被標(biāo)注為穩(wěn)定版本,生產(chǎn)環(huán)境中可以使用了,但是,相對來說,Structured Streaming還處于比較初級的階段,很多功能與dataflow相比還是有差距
數(shù)據(jù)源
- Socket source (for testing):
從socket連接中讀取文本內(nèi)容。 - File source:
以數(shù)據(jù)流的方式讀取一個目錄中的文件。支持text、csv、json、parquet等文件類型。 - Kafka source:
從Kafka中拉取數(shù)據(jù),與0.10或以上的版本兼容,后面單獨整合Kafka
輸出方式
- output mode:以哪種方式將result table的數(shù)據(jù)寫入sink
- append mode;默認(rèn)方式,新增的行才輸出,每次更新結(jié)果集時,只將新添加到結(jié)果集的結(jié)果行輸出到接收器,不支持聚合
- complete mode;所有內(nèi)容都輸出,每次觸發(fā)后,整個結(jié)果表將輸出到接收器。聚合查詢支持此功能。僅適用于包含聚合操作的查詢。
- update mode;更新的行才輸出,每次更新結(jié)果集時,僅將被更新的結(jié)果行輸出到接收器(自Spark 2.1.1起可用),不支持排序
- format/output sink的一些細(xì)節(jié):數(shù)據(jù)格式、位置等。
- file sink
- kafka sink
- foreach sink
- foreachbatch sink
- console sink
- memory sink
- query name:指定查詢的標(biāo)識。類似tempview的名字
- trigger interval:觸發(fā)間隔,如果不指定,默認(rèn)會盡可能快速地處理數(shù)據(jù)
- checkpoint地址:一般是hdfs上的目錄。注意:Socket不支持?jǐn)?shù)據(jù)恢復(fù),如果設(shè)置了,第二次啟動會報錯 ,Kafka支持
流處理模式
有狀態(tài)
- 概念:
當(dāng)前批次計算的結(jié)果與之前批次的計算結(jié)果有關(guān)系,需要進(jìn)行聚合,聚合的結(jié)果作為這個批次最后的結(jié)果
無狀態(tài)
- 概念:
每個計算批次之間是沒有關(guān)系,只對當(dāng)前自己這個批次的數(shù)據(jù)做計算,這個批次的結(jié)果就是最后輸出的結(jié)果
窗口模式
- 概念:
基于時間窗口的計算,按照數(shù)據(jù)產(chǎn)生的時間event_time來計算這個數(shù)據(jù)的結(jié)果,而不是按照數(shù)據(jù)到達(dá)的時間來表示數(shù)據(jù)的結(jié)果 - 問題:
基于時間事件event_time的窗口計算存在一個問題,當(dāng)遇到網(wǎng)絡(luò)延遲時,已經(jīng)過了時間窗口,還需不需要計算 - 水印 water mark
- 概念:窗口中允許最大的事件時間-用戶定義的超時時間(如10min)=當(dāng)前的水位線
- 場景:數(shù)據(jù)延遲到達(dá)太久,考慮是否需要計算的問題
- 內(nèi)容: 高于水印就計算,低于水印就不計算
容錯語義
- 概念:
Structured Streaming的核心設(shè)計理念和目標(biāo)之一,就是支持一次且僅一次Extracly-Once的語義 - 內(nèi)容:
- 每個streaming source都被設(shè)計成支持offset,進(jìn)而可以讓spark來追蹤讀取的位置。
- spark基于checkpoint和wal來持久化保存每個trigger interval內(nèi)處理的offset的范圍
- sink被設(shè)計成可以支持在多次計算處理時保持冪等性,就是說,用同樣的一批數(shù)據(jù),無論多少次去更新sink,都會保持一致和相同的狀態(tài)
- 總結(jié):
綜合利用基于offset的source,基于checkpoint和wal的execution engine,以及基于冪等性的sink,可以支持完整的一次且僅一次的語義。