[TOC]
本篇文章主要聚焦于 BookKeeper 內(nèi)核的實(shí)現(xiàn)機(jī)制上查邢,會(huì)從 BookKeeper 的基本概念、架構(gòu)赖歌、讀寫(xiě)一致性實(shí)現(xiàn)佳鳖、讀寫(xiě)分離實(shí)現(xiàn)、容錯(cuò)機(jī)制等方面來(lái)講述减细,因?yàn)槲也](méi)有看過(guò) BookKeeper 的源碼,所以這里的講述主要還是從原理、方案實(shí)現(xiàn)上來(lái)介紹杏死,具體如何從解決方案落地到具體的代碼實(shí)現(xiàn),有興趣的可以去看下 BookKeeper 的源碼實(shí)現(xiàn)捆交。
BookKeeper 基礎(chǔ)
正如 Apache BookKeeper 官網(wǎng)介紹的一樣:A scalable, fault-tolerant, and low-latency storage service optimized for real-time workloads淑翼。BookKeeper 的定位是一個(gè)可用于實(shí)時(shí)場(chǎng)景下的高擴(kuò)展性、強(qiáng)容錯(cuò)品追、低延遲的存儲(chǔ)服務(wù)玄括。Pulsar-Cloud Native Messaging & Streaming - 示說(shuō)網(wǎng) 中也做了一個(gè)簡(jiǎn)單總結(jié):
- 低延遲多副本復(fù)制:Quorum Parallel Replication;
- 持久化:所有操作保證在刷盤(pán)后才 ack肉瓦;
- 強(qiáng)一致性:可重復(fù)讀的一致性(Repeatable Read Consistency);
- 讀寫(xiě)高可用遭京;
- 讀寫(xiě)分離银还。
BookKeeper 基本概念
如下圖所示,一個(gè) Log/Stream/Topic 可以由下面的部分組成(圖片來(lái)自 Pulsar-Cloud Native Messaging & Streaming)洁墙。
- Ledger:它是 BK 的一個(gè)基本存儲(chǔ)單元(本質(zhì)上還是一種抽象)蛹疯,BK Client 的讀寫(xiě)操作也都是以 Ledger 為粒度的;
- Fragment:BK 的最小分布單元(實(shí)際上也是物理上的最小存儲(chǔ)單元)热监,也是 Ledger 的組成單位捺弦,默認(rèn)情況下一個(gè) Ledger 會(huì)對(duì)應(yīng)的一個(gè) Fragment(一個(gè) Ledger 也可能由多個(gè) Fragment 組成);
- Entry:每條日志都是一個(gè) Entry孝扛,它代表一個(gè) record列吼,每條 record 都會(huì)有一個(gè)對(duì)應(yīng)的 entry id;
關(guān)于 Fragment苦始,它是 Ledger 的物理組成單元寞钥,也是最小的物理存儲(chǔ)單元,在以下兩種情況下會(huì)創(chuàng)建新的 Fragment:
- 當(dāng)創(chuàng)建新的 Ledger 時(shí)陌选;
- 當(dāng)前 Fragment 使用的 Bookies 發(fā)生寫(xiě)入錯(cuò)誤或超時(shí)理郑,系統(tǒng)會(huì)在剩下的 Bookie 中新建 Fragment,但這時(shí)并不會(huì)新建 Ledger咨油,因?yàn)?Ledger 的創(chuàng)建和關(guān)閉是由 Client 控制的您炉,這里只是新建了 Fragment(需要注意的是:這兩個(gè) Fragment 對(duì)應(yīng)的 Ensemble Bookie 已經(jīng)不一樣了,但它們都屬于一個(gè) Ledger役电,這里并不一定是一個(gè) Ensemble Change 操作)赚爵。
BookKeeper 架構(gòu)設(shè)計(jì)
Apache BookKeeper 的架構(gòu)如下圖所示,它主要由三個(gè)組件構(gòu)成:客戶端 (client)法瑟、數(shù)據(jù)存儲(chǔ)節(jié)點(diǎn) (Bookie) 和元數(shù)據(jù)存儲(chǔ) Service Discovery(ZooKeeper)冀膝,Bookies 在啟動(dòng)的時(shí)候向 ZooKeeper 注冊(cè)節(jié)點(diǎn),Client 通過(guò) ZooKeeper 發(fā)現(xiàn)可用的 Bookie霎挟。
這里窝剖,我們可以看到 BookKeeper 架構(gòu)屬于典型的 slave-slave 架構(gòu),zk 存儲(chǔ)其集群的 meta 信息(zk 雖是單點(diǎn)氓扛,但 zk 目前的高可用還是很有保障的)枯芬,這種模式的好處顯而易見(jiàn),server 端變得非常簡(jiǎn)單采郎,所有節(jié)點(diǎn)都是一樣的角色和處理邏輯千所,能夠這樣設(shè)計(jì)的主要原因是其副本沒(méi)有 leader 和 follower 之分,這是它與一些常見(jiàn) mq(如:kafka蒜埋、RocketMQ)系統(tǒng)的典型區(qū)別淫痰,每種設(shè)計(jì)都有其 trade-off,BeekKeeper 從設(shè)計(jì)之初就是為了高可靠而設(shè)計(jì)整份。
BookKeeper 存儲(chǔ)層實(shí)現(xiàn)
Apache BookKeeper 是一個(gè)高可靠的分布式存儲(chǔ)系統(tǒng)待错,存儲(chǔ)層的實(shí)現(xiàn)是其核心籽孙,對(duì)一個(gè)存儲(chǔ)系統(tǒng)來(lái)說(shuō),關(guān)鍵的幾點(diǎn)實(shí)現(xiàn)火俄,無(wú)非是:一致性如何保證犯建、IO 如何優(yōu)化、高可用如何實(shí)現(xiàn)等瓜客,這小節(jié)就讓我們揭開(kāi)其神秘面紗适瓦。
新建 Ledger
Ledger 是 BookKeeper 的基本存儲(chǔ)抽象單元,這里先看下一個(gè) Ledger 是如何創(chuàng)建的谱仪,這里會(huì)介紹一些關(guān)于 Ledger 存儲(chǔ)層的一些重要概念(圖片來(lái)自 Pulsar-Cloud Native Messaging & Streaming)玻熙。
Ledger 是一組追加有序的記錄,它是由 Client 創(chuàng)建的疯攒,然后由其進(jìn)行追加寫(xiě)操作嗦随。每個(gè) Ledger 在創(chuàng)建時(shí)會(huì)被賦予全局唯一的 ID,其他的 Client 可以根據(jù) Ledger ID敬尺,對(duì)其進(jìn)行讀取操作枚尼。創(chuàng)建 Ledger 及 Entry 寫(xiě)入的相關(guān)過(guò)程如下:
- Client 在創(chuàng)建 Ledger 的時(shí)候,從 Bookie Pool 里面按照指定的數(shù)據(jù)放置策略挑選出一定數(shù)量的 Bookie筷转,構(gòu)成一個(gè) Ensemble姑原;
- 每條 Entry 會(huì)被并行地發(fā)送給 Ensemble 里面的部分 Bookies(每條 Entry 發(fā)送多少個(gè) Bookie 是由 Write Quorum size 設(shè)置悬而、具體發(fā)送哪些 Bookie 是由 Round Robin 算法來(lái)計(jì)算)呜舒,并且所有 Entry 的發(fā)送以流水線的方式進(jìn)行,也就是意味著發(fā)送第 N + 1 條記錄的寫(xiě)請(qǐng)求不需要等待發(fā)送第 N 條記錄的寫(xiě)請(qǐng)求返回笨奠;
- 對(duì)于每條 Entry 的寫(xiě)操作而言袭蝗,當(dāng)它收到 Ensemble 里面大多數(shù) Bookie 的確認(rèn)后(這個(gè)由 Ack Quorum size 來(lái)設(shè)置),Client 認(rèn)為這條記錄已經(jīng)持久化到這個(gè) Ensemble 中般婆,并且有大多數(shù)副本到腥。
這里引入了三個(gè)重要的概念,它們也是 BookKeeper 一致性的基礎(chǔ):
- Ensemble size(E):Set of Bookies across which a ledger is striped蔚袍,一個(gè) Ledger 所涉及的 Bookie 集合乡范;
- Write Quorum Size(Qw):Number of replicas,副本數(shù)啤咽;
- Ack Quorum Size(Qa):Number of responses needed before client’s write is satisfied晋辆。
從上面 Ensemble、Qw宇整、Qa 的概念可以得到以下這些推論:
- Ensemble:可以控制一個(gè) Ledger 的讀寫(xiě)帶寬瓶佳;
- Write Quorum:控制一條記錄的復(fù)本數(shù);
- Ack Quorum:寫(xiě)每條記錄需要等待的 Ack 數(shù) 鳞青,控制時(shí)延霸饲;
- 增加 Ensemble为朋,可以增加讀寫(xiě)帶寬(增加了可寫(xiě)的機(jī)器數(shù));
- 減少 Ack Quorum厚脉,可以減長(zhǎng)尾時(shí)延习寸。
一致性
對(duì)于分布式存儲(chǔ)系統(tǒng),為了高可用傻工,多副本是其通用的解決方案融涣,但也帶來(lái)了一致性的問(wèn)題,這里就看下 Apache BookKeeper 是如何解決其帶來(lái)的一致性問(wèn)題的精钮。
在介紹其讀寫(xiě)一致性之前威鹿,先看下 BK 的一致性模型(圖片來(lái)自 Twitter高性能分布式日志系統(tǒng)架構(gòu)解析)。
對(duì)于 Write 操作而言轨香,writer 不斷添加記錄忽你,每條記錄會(huì)被 writer 賦予一個(gè)嚴(yán)格遞增的 id,所有的追加操作都是異步的臂容,也就是說(shuō):第二條記錄不用等待第一條記錄返回結(jié)果科雳。所有寫(xiě)成功的操作都會(huì)按照 id 遞增順序返回 ack 給 writer。(圖片來(lái)自 Twitter高性能分布式日志系統(tǒng)架構(gòu)解析)脓杉。
伴隨著寫(xiě)成功的 ack糟秘,writer 不斷地更新一個(gè)指針叫做 Last-Add-Confirm(LAC),所有 Entry id 小于等于 LAC 的記錄保證持久化并復(fù)制到大多數(shù)副本上球散,而 LAC 與 LAP(Last-Add-Pushed)之間的記錄就是已經(jīng)發(fā)送到 Bookie 上但還未被 ack 的數(shù)據(jù)尿赚。
讀的一致性
所有的 Reader 都可以安全讀取 Entry ID 小于或者等于 LAC 的記錄,從而保證 reader 不會(huì)讀取未確認(rèn)的數(shù)據(jù)蕉堰,從而保證了 reader 之間的一致性(圖片來(lái)自 Twitter高性能分布式日志系統(tǒng)架構(gòu)解析)凌净。
寫(xiě)的一致性
從上面的介紹中,也可以看出屋讶,對(duì)于 BK 的多個(gè)副本冰寻,其并沒(méi)有 leader 和 follower 之分,因此皿渗,BK 并不會(huì)進(jìn)行相應(yīng)的選主(leader election)操作斩芭,并且限制每個(gè) Ledger 只能被一個(gè) Writer 寫(xiě),BK 通過(guò) Fencing 機(jī)制來(lái)防止出現(xiàn)多個(gè) Writer 的狀態(tài)乐疆,從而保證寫(xiě)的一致性划乖。
讀寫(xiě)分離
下面來(lái)看下 BK 存儲(chǔ)層一個(gè)很重要的設(shè)計(jì),那就是讀寫(xiě)分離機(jī)制诀拭。在論文 Durability with BookKeeper 中迁筛,關(guān)于讀寫(xiě)分離機(jī)制的介紹如下所示(圖片來(lái)自 Durability with BookKeeper):
e
A bookie uses two devices, ideally in separate physical disks:
- The journal device is a write-ahead log and stores synchronously and sequentially all updates the bookie executes.
- The ledger device contains an indexed copy of a ledger fragment, which a bookie uses to respond to read requests.
上面是論文中關(guān)于 BK 讀寫(xiě)分離機(jī)制實(shí)現(xiàn)的介紹,我當(dāng)時(shí)在看完上面的記錄之后,腦海中有以下疑問(wèn):
- 一個(gè)寫(xiě)請(qǐng)求是怎么處理细卧?什么時(shí)候數(shù)據(jù)被認(rèn)為是 ack 了尉桩;
- 數(shù)據(jù)肯定先寫(xiě)到 Journal Device 中的,那么數(shù)據(jù)是如何到 Ledger Device 中的贪庙?
- Ledger Device 中的順序?qū)懜S機(jī)讀是什么意思蜘犁?難道跟 RocketMQ 的存儲(chǔ)結(jié)構(gòu)一樣?
- Ledger Device 底層是怎么切分實(shí)際的物理文件的止邮?
- 數(shù)據(jù)在什么時(shí)候才能可見(jiàn)这橙?
- 在從 Ledger Device 讀數(shù)據(jù)時(shí),它是通過(guò)什么機(jī)制提高查詢速度的导披?
帶著這些疑問(wèn)屈扎,接下來(lái)來(lái)分析其實(shí)現(xiàn)(圖片來(lái)自 Pulsar-Cloud Native Messaging & Streaming):
Journal Device 分析:
- 處理寫(xiě)入請(qǐng)求時(shí),如果 Journal 是在專(zhuān)用的磁盤(pán)上撩匕,由于是順序?qū)懭胨⒈P(pán)鹰晨,性能會(huì)很高;
Ledger Device 的實(shí)現(xiàn):
- Bookie 最初的設(shè)計(jì)方案是每個(gè) Ledger 對(duì)應(yīng)一個(gè)物理文件止毕,但這樣會(huì)極大消耗寫(xiě)性能模蜡,所以 Bookie 當(dāng)前的設(shè)計(jì)方案是所有 Ledger 都寫(xiě)一個(gè)單獨(dú)的文件中,這個(gè)文件又叫 entry log扁凛;
- 寫(xiě)入時(shí)忍疾,不但會(huì)寫(xiě)入到 Journal 中還會(huì)寫(xiě)入到緩存(memtable)中,定期會(huì)做刷盤(pán)(刷盤(pán)前會(huì)做排序谨朝,通過(guò) 聚合+排序 優(yōu)化讀取性能)卤妒;
- 優(yōu)化查找:Ledger Device 中會(huì)維護(hù)一個(gè)索引結(jié)構(gòu),存儲(chǔ)在 RocksDB 中叠必,它會(huì)將 (LedgerId荚孵,EntryId) 映射到(EntryLogId,文件中的偏移量)纬朝。
讀寫(xiě)流程
了解完 BK 的一致性模型和讀寫(xiě)分離機(jī)制之后,這里來(lái)看下 BK 的讀寫(xiě)流程骄呼。
Entry 寫(xiě)入流程
了解完 BK 的一致性模型和讀寫(xiě)分離機(jī)制之后共苛,這里來(lái)看下 BK 的讀寫(xiě)流程。
Entry 寫(xiě)入流程
這里以一個(gè)例子來(lái)說(shuō)明蜓萄,假設(shè) E 是3隅茎,Qw 和 Qa 是2,那么 Entry 寫(xiě)入如下圖(圖片來(lái)自 Durability with BookKeeper):
- Writer 會(huì)先分配對(duì)應(yīng)的 id嫉沽,然后按照 round-robin 算法從3個(gè) Bookie 中選取2個(gè) Bookie辟犀;
- Writer 會(huì)向兩個(gè) Bookie 發(fā)送寫(xiě)入請(qǐng)求,因?yàn)?Qa 設(shè)置為2绸硕,只有收到兩個(gè) ack 響應(yīng)后堂竟,才會(huì)認(rèn)為這條 Entry 寫(xiě)入成功魂毁;
如果寫(xiě)入過(guò)程中有一臺(tái) Bookie 掛了怎么辦?
- 那么只能向另外2臺(tái) Bookie 寫(xiě)入數(shù)據(jù)出嘹;
- 這時(shí)候這個(gè) Ledger 會(huì)新建一個(gè) Fragment席楚,假設(shè)掛的是A,之前 Ensemble 是 A税稼、B烦秩、C,現(xiàn)在的是 B郎仆、C只祠;
- 這個(gè)變化會(huì)更新到 zk 中這個(gè) Ledger 的 meta 中。
如果寫(xiě)入過(guò)程中有兩個(gè) Bookie 掛了怎么辦扰肌?
- Ensemble 里面的存活的 Bookies 不能滿足 Qw 的要求铆农;
- Client 會(huì)進(jìn)行一個(gè) Ensemble Change 操作;
- Ensemble Change 將從 Bookie Pool 中根據(jù)數(shù)據(jù)放置策略挑選出額外的 Bookie 用來(lái)取代那些不存活的 Bookie 狡耻。
Entry 讀取流程
這里依然以一個(gè)例子做說(shuō)明墩剖,例子是緊接著上面的示例,如下圖所示(圖片來(lái)自 Durability with BookKeeper):
如何想要讀取 id 為1的那條 Entry 應(yīng)該怎么做夷狰?
- 在讀取會(huì)選擇最優(yōu)的 Bookie岭皂,有了 Entry 的 id 和 Ledger 的 Ensemble 就可以根據(jù) round-robin 計(jì)算出其所在 Bookie 信息,會(huì)選擇向其中一個(gè) Bookie 發(fā)送讀請(qǐng)求沼头。
這種機(jī)制會(huì)導(dǎo)致爷绘,讀取數(shù)據(jù)時(shí)可能需要從多個(gè) Bookie 獲取數(shù)據(jù),需要并發(fā)訪問(wèn)多個(gè) Bookie进倍,性能會(huì)變差土至,極端情況會(huì)有這個(gè)問(wèn)題。
- BK 有一個(gè)優(yōu)化策略:讀取時(shí)一般是選擇讀一段數(shù)據(jù)猾昆,如果 entries 在同一臺(tái)機(jī)器上陶因,會(huì)從同一個(gè) Bookie 把這批 Entry 全部讀取。
BK 怎么處理長(zhǎng)尾效應(yīng)的問(wèn)題(長(zhǎng)尾效應(yīng)指的是某臺(tái)機(jī)器上某段或者某條數(shù)據(jù)讀取得比較慢垂蜗,進(jìn)而影響了整體的效率)楷扬?
- Client 可以向任意一個(gè)副本讀取相應(yīng)的 Entry,但為了保證低延時(shí)贴见,這里使用了一個(gè)叫 Speculative Read 的機(jī)制烘苹。讀請(qǐng)求首先發(fā)送給第一個(gè)副本后,如果在指定的時(shí)間內(nèi)沒(méi)有收到 reponse片部,則發(fā)送讀請(qǐng)求給第二個(gè)副本镣衡,然后同時(shí)等待第一個(gè)和第二個(gè)副本。誰(shuí)第一個(gè)返回,即讀取成功廊鸥。通過(guò)有效的 Speculative read望浩,可以很大程度減少長(zhǎng)尾效應(yīng)。
BookKeeper 容錯(cuò)機(jī)制
Fencing 機(jī)制
Fencing 機(jī)制在前面已經(jīng)簡(jiǎn)單介紹過(guò)了黍图,它目的主要是為了保證寫(xiě)的一致性曾雕,嚴(yán)格保證一個(gè) Ledger 只能被一個(gè) Writer 來(lái)寫(xiě)。
Fencing 怎么觸發(fā)呢助被?
- 如果一個(gè) Writer 打開(kāi)一個(gè) Ledger剖张,發(fā)現(xiàn)這個(gè) Ledger 存在,并且沒(méi)有 close揩环,這種情況下搔弄,就會(huì)觸發(fā) Fencing 策略,并且觸發(fā) Ledger Recovery丰滑。
Log Recovery 機(jī)制
一個(gè) Ledger 正常關(guān)閉后顾犹,會(huì)在其 Metadata 中存儲(chǔ) the last entry 的信息,所以正常關(guān)閉一個(gè) Ledger 是非常重要的(Ledger 一旦關(guān)閉褒墨,其就是不可變的炫刷,讀取的時(shí)候可以從任意一個(gè) Bookie 上讀取,而不需要再取 care 這個(gè) Ledger 的 LAC 信息)郁妈,否則可能會(huì)出現(xiàn)這樣一種情況:
由于 Writer 掛了(Ledger 未正常關(guān)閉)浑玛,導(dǎo)致部分?jǐn)?shù)據(jù)寫(xiě)入成功,實(shí)際上這個(gè)條消息并不滿足 Qw(可能滿足了 Qa)噩咪,會(huì)導(dǎo)致不同 Reader 讀取的結(jié)果不一致顾彰!如下圖所示:
解決方案就是: Log Recovery,正常關(guān)閉這個(gè) Ledger胃碾,并將 The Last Entry 及狀態(tài)更新到 metadata 中涨享。
Log Recovery 怎么實(shí)現(xiàn)呢?通常有兩種方案:
- 遍歷這個(gè) Ledger 所有 Entry 進(jìn)行恢復(fù)仆百;
- 利用 LAC 機(jī)制可以加速 recovery:恢復(fù)前厕隧,先獲取每個(gè) Ledger 的 LAC 信息,然后從 LAC 開(kāi)始恢復(fù)儒旬;
很明顯栏账,第二種方案是比較合理的恢復(fù)速度更快。
Bookie 容錯(cuò)
當(dāng)一個(gè) Bookie 故障時(shí):
- 所有在這個(gè) Bookie 上的 Ledgers 都處于 under-replica 狀態(tài)栈源,恢復(fù)就是復(fù)制 Fragment (Ledger 的組成單位)的過(guò)程,以確保每個(gè) Ledger 維護(hù)的副本數(shù)打到 Qw竖般。
Bk 提供自動(dòng)和手動(dòng)兩種方式:兩種方式的復(fù)制協(xié)議是一樣的甚垦;自動(dòng)恢復(fù)是 BK 內(nèi)部自動(dòng)觸發(fā),手動(dòng)過(guò)程需要手動(dòng)干預(yù),這里重點(diǎn)介紹自動(dòng)過(guò)程:
- 自動(dòng)恢復(fù)是在 Bookie 上運(yùn)行 AutoRecoveryMain 線程來(lái)實(shí)現(xiàn)艰亮,它會(huì)首先通過(guò) zk 選舉一個(gè) Auditor闭翩;
- Auditor 的作用是檢查不可用的 Bookie,然后做下面的操作:讀取 zk 上完整的 Ledgers 信息迄埃,找到失敗的 Ledgers(副本不滿足條件的)疗韵;然后在 zk 的 /underreplicated znode 節(jié)點(diǎn)創(chuàng)建重新復(fù)制任務(wù);
-
AutoRecoveryMain 還有 Replicator Worker 線程會(huì)復(fù)制相應(yīng)的 Fragment 到自己的 Ledger 上侄非,如果復(fù)制后滿足 Fully Replicated蕉汪,那么就從 zk 的節(jié)點(diǎn)中刪除這個(gè)任務(wù);
每個(gè) Bookie 在發(fā)現(xiàn)任務(wù)時(shí)會(huì)嘗試鎖定逞怨,如果無(wú)法鎖定就會(huì)執(zhí)行后面的任務(wù)者疤。如果獲得鎖,那么:
- 掃描 Ledgers叠赦,查找不屬于當(dāng)前 Bookie 的 Fragment驹马;
- 對(duì)于每個(gè)匹配的 Fragment,它將另一個(gè) Bookie 的數(shù)據(jù)復(fù)制到它自己的 Bookie除秀,用新的集合更新 Zookeeper 并將 Fragment 標(biāo)識(shí)為 Fully Replicated糯累。
如果 Ledgers 仍然存在副本數(shù)不足的 Fragment,則釋放鎖册踩。如果所有 Fragment 都已經(jīng)Fully Replicated泳姐,則從 /underreplicated 刪除重復(fù)復(fù)制任務(wù)。
寫(xiě)一致性:Fencing機(jī)制
簡(jiǎn)單來(lái)說(shuō)棍好,F(xiàn)encing機(jī)制用于防止有多個(gè)writer(pulsar中即為broker)同時(shí)寫(xiě)同一個(gè)topic/partition
什么時(shí)候會(huì)出現(xiàn)多個(gè)writer同時(shí)寫(xiě)同一個(gè)topic呢仗岸?在pulsar中,當(dāng)zk檢測(cè)到有一個(gè)broker1掛掉了借笙,那么會(huì)把該broker1擁有的topic所有權(quán)轉(zhuǎn)移到另一個(gè)broker2扒怖。如果broker1實(shí)際上沒(méi)掛掉(類(lèi)似出現(xiàn)腦裂的情況),那么會(huì)出現(xiàn)broker1业稼、broker2同時(shí)寫(xiě)同一個(gè)topic盗痒,對(duì)于broker1寫(xiě)入完成的數(shù)據(jù),由于topic已經(jīng)給broker2接管了低散,在broker2看來(lái)并不知道broker1寫(xiě)入了數(shù)據(jù)俯邓,就會(huì)出現(xiàn)寫(xiě)入數(shù)據(jù)的不一致。
Broker Recovery:Fencing
Broker crash熔号,或 Broker 與 ZK 出現(xiàn)網(wǎng)絡(luò)分區(qū)導(dǎo)致腦裂稽鞭,需進(jìn)行 partition ownership 轉(zhuǎn)移。
- Broker1 心跳超時(shí)后引镊,ZK 將 topic partition 的 ownership 轉(zhuǎn)移到 Broker2
- Broker2 向 Ensemble 發(fā)起 Fencing ledger_X 請(qǐng)求朦蕴,Bookies 紛紛將 ledger_X 置為 Fencing 不可寫(xiě)狀態(tài)篮条。
- Broker1 寫(xiě)數(shù)據(jù)失敗收到 FenceException,說(shuō)明該 partition 已被 Broker 接管吩抓,主動(dòng)放棄 ownership
- Client 收到異常后與 Broker1 斷開(kāi)連接涉茧,進(jìn)行 Topic Lookup 與 Broker2 建立長(zhǎng)連接。
- 同時(shí)疹娶,Broker2 對(duì) ledger_X LAC1 之后的 entry log 依次逐一進(jìn)行 Forwarding Recovery(若 unknow 狀態(tài)的 entry 副本數(shù)實(shí)際上已達(dá)到 WQ伴栓,則認(rèn)為該 entry 寫(xiě)成功,LAC1 自增為 LAC2)
-
Broker2 更新 ledger_X 的 metadata雨饺,將其置為 CLOSE 狀態(tài)钳垮,再創(chuàng)建新 ledger,繼續(xù)處理 Client 的寫(xiě)請(qǐng)求沛膳。