都2023年了,你還不懂批處理和流處理的區(qū)別?
Spark?&& Flink
就目前最熱的兩種流計算引擎Apache Spark和Apache Flink而言,誰最終會成為No1呢?單從 "低延時" 的角度看,Spark是Micro Batching(微批式)模式,最低延遲Spark能達到0.5~2秒左右,F(xiàn)link是Native Streaming(純流式)模式,最低延時能達到微秒。很顯然是相對較晚出道的 Apache Flink 后來者居上。那么為什么Apache Flink能做到如此之 "快"呢??
根本原因是Apache Flink 設(shè)計之初就認為 "批是流的特例",整個系統(tǒng)是Native Streaming設(shè)計,每來一條數(shù)據(jù)都能夠觸發(fā)計算。相對于需要靠時間來積攢數(shù)據(jù)Micro Batching模式來說,在架構(gòu)上就已經(jīng)占據(jù)了絕對優(yōu)勢。
1.場景引入分析
日常工作中,一般會先把數(shù)據(jù)儲存在一張表中,然后對這張表的數(shù)據(jù)進行加工、分析。既然數(shù)據(jù)要儲存在表中,就有時效性這個概念。
如果處理的是”年級別“的數(shù)據(jù),比如人口分析、宏觀經(jīng)濟分析,那么數(shù)據(jù)最新日期距今間隔一兩周、甚至一兩個月都沒什么關(guān)系。
如果處理的是”天級別“的數(shù)據(jù),比如各大網(wǎng)站的用戶偏好分析、零售供銷分析,一般晚個幾天也是可以的,即 T+N 更新。
如果是”小時級別“的數(shù)據(jù),對時效性要求就更高了,比如金融風控,涉及到資金的安全,必須有一張小時級別的數(shù)據(jù)。
那么還有沒有要求更高的?當然有了,比如風險監(jiān)測,網(wǎng)站必須有實時監(jiān)測系統(tǒng),一旦有攻擊,就必須立刻采取措施,雙十一或者周年慶的時候,各大電商平臺都經(jīng)歷著嚴峻的流量考驗,也必須對系統(tǒng)進行實時的監(jiān)測。此外,網(wǎng)站的實時個性化推薦、搜索引擎中也對實時性有極高的要求。
在這種場景下,傳統(tǒng)的數(shù)據(jù)處理流程——先收集數(shù)據(jù),然后放到DB中,再取出來分析——就無法滿足這么高的實時要求,因此產(chǎn)生了“流式計算”的處理方法。

2.流式計算與批量計算
收集數(shù)據(jù) - 放到DB中 - 取出來分析的傳統(tǒng)的流程,叫做批量計算,顧名思義,將數(shù)據(jù)存起來,批量進行計算。
流式計算是對數(shù)據(jù)流進行實時計算,它不是更快的批計算,可以說,是完全不同的處理思路。
通過與批量計算進行對比的方式,介紹下其原理:
(1) 與批量計算那樣慢慢積累數(shù)據(jù)不同,流式計算將大量數(shù)據(jù)平攤到每個時間點上,連續(xù)地進行小批量的進行傳輸,數(shù)據(jù)持續(xù)流動,計算完之后就丟棄。
(2) 批量計算是維護一張表,對表進行實施各種計算邏輯。流式計算相反,是必須先定義好計算邏輯,提交到流式計算系統(tǒng),這個計算作業(yè)邏輯在整個運行期間是不可更改的。
(3) 計算結(jié)果上,批量計算對一段時間內(nèi)的全部數(shù)據(jù)進行計算后傳輸結(jié)果,流式計算是每次小批量計算后,結(jié)果可以立刻投遞到在線系統(tǒng),做到實時化展現(xiàn)。
3.總結(jié)與相關(guān)產(chǎn)品
?流式計算流程
① 提交流計算作業(yè);
② 等待流式數(shù)據(jù)觸發(fā)流計算作業(yè);
③ 計算結(jié)果持續(xù)不斷對外寫出。
?流式計算特點
① 實時、低延遲;
② 無界,數(shù)據(jù)是不斷無終止的;
③ 連續(xù),計算持續(xù)進行,計算完之后數(shù)據(jù)即丟棄;
④ 數(shù)據(jù)量大,但是不十分關(guān)注存儲,一旦經(jīng)過處理,要么被丟棄,要么被歸檔存儲;
⑤ 注重數(shù)據(jù)的整體價值,不過分關(guān)注個別數(shù)據(jù);
⑥ 數(shù)據(jù)順序顛倒,或者不完整,系統(tǒng)無法控制將要處理的新到達的數(shù)據(jù)元素的順序。
?流式計算特征
① 無界(Unbounded)
數(shù)據(jù)記錄(record)在計算過程中不斷地動態(tài)到達,與批處理不同,計算過程開始之前就知道數(shù)據(jù)大小與邊界,更容易優(yōu)化
② 亂序(Out-of-order)
record的原始順序和在處理節(jié)點上的處理順序可能不一致,shuffle過程(數(shù)據(jù)傳遞)也可能導致順序改變
③ 延遲(Delay)
record的產(chǎn)生時間和在處理節(jié)點上的處理時間可能差別很大
?流式系統(tǒng)相關(guān)產(chǎn)品
列舉一下流式計算的相關(guān)產(chǎn)品,不具體盤點,對流式計算感興趣可以了解一下:
Apache Storm:Twitter 開發(fā)的第一代流處理系統(tǒng)
Heron:Twitter 開發(fā)的第二代流處理系統(tǒng)
Apache Spark streaming:
Apache Flink:
Apache Kafka:linkedin開發(fā)的一種高吞吐量的分布式發(fā)布訂閱消息系統(tǒng),它可以處理消費者規(guī)模的網(wǎng)站中的所有動作流數(shù)據(jù)。
Apache Samza

批量和流式的區(qū)別:
1.數(shù)據(jù)處理單位:
批量計算按數(shù)據(jù)塊來處理數(shù)據(jù),每一個task接收一定大小的數(shù)據(jù)塊,比如MR,map任務(wù)在處理完一個完整的數(shù)據(jù)塊后(比如128M),然后將中間數(shù)據(jù)發(fā)送給reduce任務(wù)。
流式計算的上游算子處理完一條數(shù)據(jù)后,會立馬發(fā)送給下游算子,所以一條數(shù)據(jù)從進入流式系統(tǒng)到輸出結(jié)果的時間間隔較短(當然有的流式系統(tǒng)為了保證吞吐,也會對數(shù)據(jù)做buffer)。
這樣的結(jié)果就是:批量計算往往得等任務(wù)全部跑完之后才能得到結(jié)果,而流式計算則可以實時獲取最新的計算結(jié)果。
2.數(shù)據(jù)源:
批量計算通常處理的是有限數(shù)據(jù)(bound data),數(shù)據(jù)源一般采用文件系統(tǒng),而流式計算通常處理無限數(shù)據(jù)(unbound data),一般采用消息隊列作為數(shù)據(jù)源。
3.任務(wù)類型:
批量計算中的每個任務(wù)都是短任務(wù),任務(wù)在處理完其負責的數(shù)據(jù)后關(guān)閉,而流式計算往往是長任務(wù),每個work一直運行,持續(xù)接受數(shù)據(jù)源傳過來的數(shù)據(jù)。
離線=批量?實時=流式?
習慣上認為離線和批量等價;實時和流式等價,但其實這種觀點并不完全正確。
假設(shè)一種情況:當擁有一個非常強大的硬件系統(tǒng),可以毫秒級的處理Gb級別的數(shù)據(jù),那么批量計算也可以毫秒級得到統(tǒng)計結(jié)果(當然這種情況非常極端,目前不可能),那還能說它是離線計算嗎?
所以說離線和實時應(yīng)該指的是:數(shù)據(jù)處理的延遲;批量和流式指的是:數(shù)據(jù)處理的方式。兩者并沒有必然的關(guān)系。事實上Spark streaming就是采用小批量(batch)的方式來實現(xiàn)實時計算。
可以參考下面鏈接:https://www.oreilly.com/ideas/the-world-beyond-batch-streaming-101。作者是Google實時計算的負責人,里面闡述了他對批量和實時的理解,并且作者認為批量計算只是流式計算的子集,一個設(shè)計良好的流式系統(tǒng)完全可以替代批量系統(tǒng)
關(guān)于Flink的流處理與批處理
在大數(shù)據(jù)處理領(lǐng)域,批處理任務(wù)與流處理任務(wù)一般被認為是兩種不同的任務(wù),一個大數(shù)據(jù)框架一般會被設(shè)計為只能處理其中一種任務(wù)。
例如Storm只支持流處理任務(wù),而MR和Spark只支持批處理任務(wù)。Spark Streaming是Spark之上支持流處理任務(wù)的子系統(tǒng),看似是一個特例,其實并不是,Spark Streaming采用了一種micro-batch的架構(gòu),就把輸入數(shù)據(jù)流切分成細粒度的batch,并為每個batch數(shù)據(jù)提交一個批處理Spark任務(wù),所以Spark Streaming本質(zhì)上還是基于Spark批處理系統(tǒng)對流式數(shù)據(jù)進行處理,和Storm等完全流式的數(shù)據(jù)處理方式是完全不同的。而Flink通過靈活的執(zhí)行引擎,能夠同時支持批處理任務(wù)與流處理任務(wù)。
在執(zhí)行引擎這一層,流處理系統(tǒng)與批處理系統(tǒng)最大不同在于節(jié)點間的數(shù)據(jù)傳輸方式。對于一個流處理系統(tǒng),其節(jié)點間數(shù)據(jù)傳輸?shù)臉藴誓P褪牵寒斠粭l數(shù)據(jù)被處理完成后,序列化到緩存中,然后立刻通過網(wǎng)絡(luò)傳輸?shù)较乱粋€節(jié)點,由下一個節(jié)點繼續(xù)處理。而對于一個批處理系統(tǒng),其節(jié)點間效據(jù)傳輸?shù)臉藴誓P褪牵寒斠粭l數(shù)據(jù)被處理完成后,序列化到緩存中,并不會立刻通過網(wǎng)絡(luò)傳輸?shù)较乱粋€節(jié)點,當緩存寫滿,就持久化到本地硬盤上,當所有數(shù)據(jù)都被處理完成后,才開始將處理后的數(shù)據(jù)通過網(wǎng)絡(luò)傳輸?shù)较乱粋€節(jié)點。這兩種數(shù)據(jù)傳輸模式是兩個極端,對應(yīng)的是流處理系統(tǒng)對低延遲的要求和批處理系統(tǒng)對高吞吐量的要求。
Flink的執(zhí)行引擎采用了一種十分靈活的方式,同時支持了這兩種數(shù)據(jù)傳輸模型。Flink以固定的緩存塊為單位進行網(wǎng)絡(luò)數(shù)據(jù)傳輸,用戶可以通過緩存塊超時值指定緩存塊的傳輸時機。如果緩存塊的超時值為0,則Flink的數(shù)據(jù)傳輸方式類似上文所提到流處理系統(tǒng)的標準模型,此時系統(tǒng)可以獲得最低的處理延遲。如果緩存塊的超時值為無限大,則Flink的數(shù)據(jù)傳輸方式類似上文所提到批處理系統(tǒng)的標準模型,此時系統(tǒng)可以獲得最高的吞吐量。同時緩存塊的超時值也可以設(shè)置為0到無限大之間的任意值。緩存塊的超時閥值越小,則Flink流處理執(zhí)行引擎的數(shù)據(jù)處理延遲越低,但吞吐量也會降低,反之亦然。通過調(diào)整緩存塊的超時閥值,用戶可根據(jù)需求靈話地權(quán)衡系統(tǒng)延遲和吞吐量。

Flink和Spark Streaming的本質(zhì)區(qū)別:
傳統(tǒng)的批處理方法
傳統(tǒng)批處理方法是持續(xù)收取數(shù)據(jù),以時間作為劃分多個批次的依據(jù),再周期性地執(zhí)行批次運算。但假設(shè)需要計算每小時出現(xiàn)事件轉(zhuǎn)換的次數(shù),如果事件轉(zhuǎn)換跨越了所定義的時間劃分,傳統(tǒng)批處理會將中介運算結(jié)果帶到下一個批次進行計算;除此之外,當出現(xiàn)接收到的事件順序顛倒情況下,傳統(tǒng)批處理仍會將中介狀態(tài)帶到下一批次的運算結(jié)果中,這種處理方式也不盡如人意。
理想方法
第一點,要有理想方法,這個理想方法是引擎必須要有能力可以累積狀態(tài)和維護狀態(tài),累積狀態(tài)代表著過去歷史中接收過的所有事件,會影響到輸出。
第二點,時間,時間意味著引擎對于數(shù)據(jù)完整性有機制可以操控,當所有數(shù)據(jù)都完全接受到后,輸出計算結(jié)果。
第三點,理想方法模型需要實時產(chǎn)生結(jié)果,但更重要的是采用新的持續(xù)性數(shù)據(jù)處理模型來處理實時數(shù)據(jù),這樣才最符合 continuous data 的特性。
流式處理:
流式處理簡單來講即有一個無窮無盡的數(shù)據(jù)源在持續(xù)收取數(shù)據(jù),以代碼作為數(shù)據(jù)處理的基礎(chǔ)邏輯,數(shù)據(jù)源的數(shù)據(jù)經(jīng)過代碼處理后產(chǎn)生出結(jié)果,然后輸出,這就是流式處理的基本原理。
分布式流式處理:
假設(shè) Input Streams 有很多個使用者,每個使用者都有自己的 ID,如果計算每個使用者出現(xiàn)的次數(shù),需要讓同一個使用者的出現(xiàn)事件流到同一運算代碼,這跟其他批次需要做 group by 是同樣的概念,所以跟 Stream 一樣需要做分區(qū),設(shè)定相應(yīng)的 key,然后讓同樣的 key 流到同一個 computation instance 做同樣的運算。
有狀態(tài)分布式流式處理:
上述代碼中定義了變數(shù) x,x 在數(shù)據(jù)處理過程中會進行讀和寫,在最后輸出結(jié)果時,可以依據(jù)變數(shù) x 決定輸出的內(nèi)容,即狀態(tài) x 會影響最終的輸出結(jié)果。
這個過程中,第一個重點是先進行了狀態(tài) co-partitioned by key,同樣的 key 都會流到 computation instance,與使用者出現(xiàn)次數(shù)的原理相同,次數(shù)即所謂的狀態(tài),這個狀態(tài)一定會跟同一個 key 的事件累積在同一個 computation instance。相當于根據(jù)輸入流的 key 重新分區(qū)的狀態(tài),當分區(qū)進入 stream 之后,這個 stream 會累積起來的狀態(tài)也變成 co-partiton 了。
第二個重點是 embeded local state backend。有狀態(tài)分散式流式處理的引擎,狀態(tài)可能會累積到非常大,當 key 非常多時,狀態(tài)可能就會超出單一節(jié)點的 memory 的負荷量,這時候狀態(tài)必須有狀態(tài)后端去維護它;在這個狀態(tài)后端在正常狀況下,用 in-memory 維護即可。

更多關(guān)于大數(shù)據(jù)開發(fā)、數(shù)倉、企業(yè)實戰(zhàn)、企業(yè)數(shù)據(jù)治理相關(guān)問題的交流,可以關(guān)注我們的公眾號和視頻號。動動大家的小手,轉(zhuǎn)發(fā)、點贊、評論起來!
