Flink 状态一致性:端到端状态一致性的保证
文章目錄
- 狀態(tài)一致性
- 什么是狀態(tài)一致性
- 狀態(tài)一致性種類(lèi)
- 端到端(end-to-end)狀態(tài)一致性
- Sink端到端狀態(tài)一致性的保證
- Flink+Kafka端到端狀態(tài)一致性的保證
狀態(tài)一致性
什么是狀態(tài)一致性
-
有狀態(tài)的流處理,內(nèi)部每個(gè)算子任務(wù)都可以有自己的狀態(tài)。
-
對(duì)于流處理器內(nèi)部(沒(méi)有接入sink)來(lái)說(shuō),所謂的狀態(tài)一致性,其實(shí)就是我們所說(shuō)的計(jì)算結(jié)果要保證準(zhǔn)確,一條數(shù)據(jù)不應(yīng)該丟失,也不應(yīng)該重復(fù)計(jì)算。
-
在遇到故障時(shí)可以恢復(fù)狀態(tài),恢復(fù)以后的重新計(jì)算,結(jié)果應(yīng)該也是完全正常的。
狀態(tài)一致性種類(lèi)
-
最多一次(At-Most-Once)
-
任務(wù)發(fā)生故障時(shí)最簡(jiǎn)單的措施就是既不恢復(fù)丟失的狀態(tài),也不重放丟失的事件,所以至多一次是最簡(jiǎn)單的一種情況。
-
它保證了每個(gè)事件至多被處理一次。
-
-
至少一次(At-Least-Once)
- 對(duì)于大多數(shù)現(xiàn)實(shí)應(yīng)用而言,用戶(hù)的期望是不丟事件,這類(lèi)保障被稱(chēng)為至少一次。
- 它意味著所有事件最終都會(huì)處理,雖然有些可能會(huì)處理多次。
-
精確一次(Exactly-Once)
- 精確一次是最嚴(yán)格,最難實(shí)現(xiàn)的一類(lèi)保障。
- 它不但能夠保證事件沒(méi)有丟失,而且每個(gè)事件對(duì)于內(nèi)部狀態(tài)的更新都只有一次。
- Flink利用Checkpoints機(jī)制來(lái)保證精確一次語(yǔ)義。
端到端(end-to-end)狀態(tài)一致性
端到端的保障指的是在整個(gè)數(shù)據(jù)處理管道上結(jié)果都是正確的。在每個(gè)組件都提供自身的保障情況下,整個(gè)處理管道上端到端的保障會(huì)受制于保障最弱的那個(gè)組件。
那么端到端的精確一次在各部分又是如何實(shí)現(xiàn)的呢?
- 內(nèi)部:Checkpoints機(jī)制,在發(fā)生故障的時(shí)候能夠恢復(fù)各個(gè)環(huán)節(jié)的數(shù)據(jù)。
- Source:可設(shè)置數(shù)據(jù)讀取的偏移量,當(dāng)發(fā)生故障的時(shí)候重置偏移量到故障之前的位置。
- Sink:從故障恢復(fù)時(shí),數(shù)據(jù)不會(huì)重復(fù)寫(xiě)入外部系統(tǒng)。
其中前兩種在上文已經(jīng)介紹過(guò)了,下面就介紹一下Sink如何提供端到端的精確一次性保障。
Sink端到端狀態(tài)一致性的保證
應(yīng)用若是想提供端到端的精確一次性保障,就需要一些特殊的Sink連接器,根據(jù)情況不同,這些連接器可以使用兩種技術(shù)來(lái)實(shí)現(xiàn)精確一次保障:
-
冪等性寫(xiě)(idempotent write)
- 冪等操作的含義就是可以多次執(zhí)行,但是只會(huì)引起一次改變。
- 例如我們將相同的鍵值對(duì)插入一個(gè)哈希結(jié)構(gòu)中就是一個(gè)冪等操作, 因?yàn)橛捎谠撴I值對(duì)已存在后,無(wú)論插入多少次都不會(huì)改變結(jié)果。
- 由于可以在不改變結(jié)果的前提下多次執(zhí)行,因此冪等性寫(xiě)操作在一定程度上減輕Flink檢查點(diǎn)機(jī)制所帶來(lái)的重復(fù)結(jié)果的影響
-
事務(wù)性寫(xiě)(transactional write)
- 事務(wù)性寫(xiě)其實(shí)就是原子性寫(xiě),即只有在上次成功的檢查點(diǎn)之前計(jì)算的結(jié)果才會(huì)被寫(xiě)入外部Sink系統(tǒng)。
- 事務(wù)性寫(xiě)雖然不會(huì)像冪等性寫(xiě)那樣出現(xiàn)重放過(guò)程中的不一致現(xiàn)象,但是會(huì)增加一定延遲,因?yàn)榻Y(jié)果只有在檢查點(diǎn)完成后才對(duì)外可見(jiàn)。
- 實(shí)現(xiàn)思想:構(gòu)建的事務(wù)對(duì)應(yīng)著Checkpoints,待Checkpoints真正完成的時(shí)候,才把所有對(duì)應(yīng)的結(jié)果寫(xiě)入Sink系統(tǒng)中。
- 實(shí)現(xiàn)方式:
- 預(yù)寫(xiě)日志(Write Ahead Log,WAL)
- 兩階段提交(Two Phase Commit,2PC)
預(yù)寫(xiě)日志
- 把結(jié)果數(shù)據(jù)先當(dāng)成狀態(tài)保存,然后在收到Checkpoints完成的通知時(shí),一次性寫(xiě)入Sink系統(tǒng)。
- 簡(jiǎn)單易于實(shí)現(xiàn),由于數(shù)據(jù)提前在狀態(tài)后端做了緩存,所以無(wú)論什么Sink系統(tǒng)都能用這種方式一批搞定。
- 但同時(shí)它也存在問(wèn)題,寫(xiě)入數(shù)據(jù)時(shí)出現(xiàn)故障則會(huì)導(dǎo)致一部分?jǐn)?shù)據(jù)成功一部分失敗。
- DataStream API提供了一個(gè)模板類(lèi)GenericWriteAheadSink,來(lái)實(shí)現(xiàn)這種事務(wù)性Sink。
兩階段提交
- 對(duì)于每個(gè)Checkpoints,Sink任務(wù)會(huì)啟動(dòng)一個(gè)事務(wù),并將接下來(lái)所有接收的數(shù)據(jù)添加到事務(wù)里。
- 然后將這些數(shù)據(jù)寫(xiě)入外部 Sink,但不提交它們,這時(shí)只是“預(yù)提交”。
- 當(dāng)它收到Checkpoints完成的通知時(shí),它才正式提交事務(wù),實(shí)現(xiàn)結(jié)果的真正寫(xiě)入。
- 這種方式真正實(shí)現(xiàn)了精確一次,它需要一個(gè)提供事務(wù)支持的外部Sink系統(tǒng),Flink提供了TwoPhaseCommitSinkFunction接口。
- 對(duì)外部Sink系統(tǒng)的要求
- 外部Sink系統(tǒng)必須提供事務(wù)支持,或者Sink任務(wù)必須能夠模擬外部系統(tǒng)上的事務(wù)。
- 在Checkpoints的隔離期間里,必須能夠開(kāi)啟一個(gè)事務(wù)并接受數(shù)據(jù)寫(xiě)入。
- 在收到Checkpoints完成的通知之前,事務(wù)必須是“等待提交”的狀態(tài)。在故障恢復(fù)的情況下,這可能需要一些時(shí)間。如果這個(gè)時(shí)候 Sink系統(tǒng)關(guān)閉事務(wù)(例如超時(shí)了),那么未提交的數(shù)據(jù)就會(huì)丟失。
- Sink任務(wù)必須能夠在進(jìn)程失敗后恢復(fù)事務(wù)。
- 提交事務(wù)必須是冪等操作。
Flink+Kafka端到端狀態(tài)一致性的保證
-
內(nèi)部:利用Checkpoints機(jī)制把狀態(tài)保存,當(dāng)發(fā)生故障的時(shí)候可以恢復(fù)狀態(tài),從而保證內(nèi)部的狀態(tài)一致性。
-
source 端:Kafka Consumer作為Source,可以將偏移量保存下來(lái),當(dāng)發(fā)生故障時(shí)可以從發(fā)生故障前的偏移量重新消費(fèi)數(shù)據(jù),從而保證一致性。
-
sink端:Kafka Producer作為Sink,采用兩階段提交Sink,需要實(shí)現(xiàn)一個(gè)TwoPhaseCOmmitSinkFunction。
總結(jié)
以上是生活随笔為你收集整理的Flink 状态一致性:端到端状态一致性的保证的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 分布式系统概念 | 分布式锁:数据库、R
- 下一篇: 分布式系统概念 | 一致性协议:拜占庭将