本篇講講Flink条获,主要有
- 基于事件時(shí)間的消息處理機(jī)制
- flink的容錯(cuò)機(jī)制
都說(shuō)flink很火忠荞,那么它到底有什么過(guò)人之處呢≡孪唬看了《Flink基礎(chǔ)教程》钻洒,總結(jié)一下。
- flink性能好锄开,市面上的測(cè)試結(jié)果顯示素标,流處理方面flink較storm有更好的表現(xiàn),甚至是在某些批處理上的性能測(cè)試中萍悴,flink竟然勝出了spark头遭。
- flink能滿足基于事件時(shí)間分析的需求,市面上應(yīng)該只此一家了癣诱。
- flink的容錯(cuò)處理機(jī)制计维,能保證exact once處理。
好了撕予,介紹完特性鲫惶,來(lái)逐條講講,首先看第二點(diǎn):
基于事件時(shí)間的消息處理機(jī)制
將這個(gè)機(jī)制之前实抡,首先了解下flink的3種時(shí)間概念
- 事件時(shí)間:消息在設(shè)備中的產(chǎn)生時(shí)間
- 攝入時(shí)間:消息進(jìn)入flink的時(shí)間
-
處理時(shí)間:消息被flink中特定操作處理的時(shí)間
借用官網(wǎng)的圖來(lái)理解:
那好欠母,基于事件時(shí)間處理到底什么意思。比如我要統(tǒng)計(jì)在2019/2/20 9:10-9:15產(chǎn)生的消息總數(shù)吆寨,那么消息發(fā)生到傳入flink肯定有延時(shí)赏淌,flink中可以基于窗口函數(shù)來(lái)實(shí)現(xiàn)某一時(shí)間段流數(shù)據(jù)的處理,那么問(wèn)題來(lái)了啄清,我這個(gè)窗口函數(shù)什么時(shí)候結(jié)束六水?
有些人肯定就會(huì)想,用系統(tǒng)時(shí)間不就行了辣卒,當(dāng)服務(wù)器的時(shí)間超過(guò)了9:15掷贾,這個(gè)窗口函數(shù)就可以觸發(fā)了呀,處理這個(gè)時(shí)間段的數(shù)據(jù)添寺】瓒ⅲ基于處理時(shí)間的消息處理就是這么做的(這也是flink默認(rèn)的處理機(jī)制)。但是消息到底flink是有網(wǎng)絡(luò)延遲的计露,可能我9:14產(chǎn)生的數(shù)據(jù),9:16才到達(dá)flink,如果按照上訴策略票罐,這個(gè)窗口函數(shù)已經(jīng)觸發(fā)了叉趣,下個(gè)窗口是9:15到9:20,也不會(huì)處理這個(gè)消息该押,所以這個(gè)消息就被丟棄了疗杉。那可如何是好?
于是蚕礼,flink引入了一個(gè)叫水友叹摺(watermark)的概念。水印的作用就是決定你這個(gè)窗口函數(shù)什么時(shí)候觸發(fā)奠蹬。
水印
水印說(shuō)白了就是每個(gè)消息的時(shí)間戳朝聋,但是一個(gè)window操作只有一個(gè)水印,這說(shuō)明水印不斷再更新囤躁,這個(gè)消息的時(shí)間戳和當(dāng)前窗口函數(shù)的水印比較選最大值(最遲的)如果后來(lái)的消息小于它冀痕,就是亂序的 。 水印更新的時(shí)機(jī)有兩種策略
- 周期性狸演,默認(rèn)200ms
- 基于事件觸發(fā)
在不考慮容忍延遲的時(shí)間言蛇,如果系統(tǒng)時(shí)間大于水印,窗口函數(shù)就會(huì)觸發(fā)宵距。
如果考慮容忍延遲時(shí)間腊尚,比如:
stream.allowedLateness(Time.seconds(2))
那么,這個(gè)窗口會(huì)在水印時(shí)間比原來(lái)的設(shè)定觸發(fā)的時(shí)間再多兩秒時(shí)觸發(fā)满哪,為了等待亂序的消息婿斥,犧牲點(diǎn)時(shí)間。
關(guān)于水印的詳解翩瓜,還可以參考https://juejin.im/post/5bf95810e51d452d705fef33受扳,里面有具體的例子。
前面提到很多次窗口兔跌,簡(jiǎn)單介紹下窗口
窗口
窗口就是勘高,對(duì)某一種范圍內(nèi)數(shù)據(jù)觸發(fā)一次函數(shù)處理,這個(gè)范圍可以是時(shí)間(某一時(shí)間段消息計(jì)數(shù))坟桅,也可以是數(shù)量(5個(gè)消息的總長(zhǎng)度)华望。
時(shí)間窗口
最簡(jiǎn)單有用的,支持滾動(dòng)和滑動(dòng)仅乓。
- 滾動(dòng):兩個(gè)窗口不重疊
stream.timeWindow(Time.minute(1))
- 滑動(dòng):兩個(gè)窗口會(huì)重疊赖舟,下述代碼表示2秒的時(shí)間窗口,每隔一秒滾動(dòng)一次夸楣。
stream.timeWindow(Time.minute(2)宾抓,Time.minute(1))
計(jì)數(shù)窗口
和上面類似子漩,也有滾動(dòng),滑動(dòng)
stream.countWindow(4石洗,2)
會(huì)話窗口
stream.window(SessionWindows.withGap(Time.minute(4)))
觸發(fā)器
窗口的觸發(fā)都是有觸發(fā)器完成的幢泼,例如上面基于事件時(shí)間的窗口,觸發(fā)條件就是根據(jù)水印判斷讲衫。用戶也可以自定義觸發(fā)器
基于事件時(shí)間的消息處理機(jī)制還是很好理解的缕棵,但是市面上好像還沒(méi)有類似的流處理引擎,大多是基于處理時(shí)間的涉兽。
flink的容錯(cuò)機(jī)制
分布式系統(tǒng)頭疼的一件事便是一致性問(wèn)題招驴。說(shuō)白了,就是系統(tǒng)故障修復(fù)后能還原到故障前的什么程度枷畏。
在流處理中别厘,一致性分為3個(gè)級(jí)別:
- at-most-once(可能少讀)
- at-least-once(可能重復(fù)讀)
- exactly-once (正好)
支持at-least-once的有Storm Trident和spark streaming,但是兩者在性能上的開銷太大了矿辽。它們通過(guò)微批處理來(lái)保證丹允,就是說(shuō),無(wú)法將消息單條處理袋倔,而是等待一批完全處理完雕蔽,下一批再處理,可想而知宾娜,增加了延時(shí)批狐。而flink牛逼的地方在于它不僅保證了exactly-once而且效率很高。 那它如何保證exactly-once的呢前塔?
checkpoint
熟悉spark的同學(xué)大概都知道這個(gè)概念嚣艇,spark可以將中間rdd的計(jì)算結(jié)果保存到磁盤中,下次通過(guò)該rdd的算子华弓,就不用從頭開始計(jì)算食零,直接從這個(gè)checkpoint開始計(jì)算。
flink消息中穿插了checkpoint消息寂屏,當(dāng)遇到該消息時(shí)贰谣,每個(gè)節(jié)點(diǎn)會(huì)將當(dāng)前消息偏移量(以kafka為例),該操作中間計(jì)算結(jié)果落盤迁霎。等到恢復(fù)時(shí)吱抚,直接從該checkpoint恢復(fù)。那么考廉,還是會(huì)可能出現(xiàn)checkpoint點(diǎn)到故障時(shí)這段時(shí)間的消息會(huì)被讀兩次啊秘豹,如果是寫入到數(shù)據(jù)庫(kù),那可能就會(huì)寫兩次了昌粤。那是如何exactly-once 的凹热啤啄刹?這就涉及到端到端的一致性問(wèn)題了,類似數(shù)據(jù)庫(kù)中的事務(wù)岸更。解決方法有兩種:
- 讀已提交鸵膏,flink sink(落盤)時(shí)維護(hù)一個(gè)緩沖區(qū)膊升,等到checkpoint時(shí)怎炊,再將緩沖區(qū)數(shù)據(jù)落盤(原子型操作)
- 讀未提交,以流式方式落盤廓译,可能會(huì)重復(fù)落盤评肆。當(dāng)故障時(shí),需要回滾非区。
本篇只是分析了flink兩個(gè)方面瓜挽,后續(xù)深入了解后再更新其他特性。
參考資料 :
- 《flink基礎(chǔ)教程》
- https://juejin.im/post/5bf95810e51d452d705fef33