博文乾貨|5張圖帶你快速入門 Pulsar 的儲存引擎 BookKeeper

StreamNative發表於2021-08-17

Apache BookKeeper 是一款企業級儲存系統,最初由雅虎研究院研發,在 2011 年作為 Apache ZooKeeper 的子專案進行孵化,在 2015 年 1 月成為 Apache 頂級專案。

起初,BookKeeper 是一個預寫日誌(WAL)系統,經過幾年的發展,BookKeeper 的功能更加完善,比如為 Hadoop 分散式檔案系統(HDFS)的 NameNode 提供高可用和多副本,為訊息系統比 Pulsar 提供儲存服務,為多個資料中心提供跨機器複製。github.com/apache/puls…

使用場景

BookKeeper 最初的一個使用場景是為 HDFS 的 NameNode 儲存 edit log,如下圖:圖片

ZKFC 是一個 ZooKeeper 的客戶端,主要用來監測和管理 NameNode 狀態,每個 NameNode 機器上都會執行一個 ZKFC,它的職責主要有三個:

•健康檢查•ZooKeeper 會話管理•選舉,當叢集中一個 Active NameNode 當機,ZooKeeper 會自動選擇一個節點作為新的 Active NameNode。

BookKeeper 記錄 NameNode 的 edit log(edit log 存放檔案系統的操作日誌),NameNode 的所有修改都會記錄到 BookKeeper。這樣 active NameNode 當機後,BookKeeper 用儲存的 edit log 去 standby NameNode 做回放,之後切換成 active NameNode。

BookKeeper 具有如下特性:

•一致性:因為 edit log 儲存的是 HDFS 的後設資料,對一致性要求很高•低延遲:為了不丟資料,需要低延遲•高吞吐:為了支援更多的 NameNode 節點,需要高吞吐

節點對等

Bookie 中儲存的資料結構如下圖:

圖片

writer 寫資料時,把 entry 併發寫入多 個 bookie 節點的 Ledger。這類似於檔案系統寫資料時首先會開啟一個檔案,如果檔案不存在,則會建立檔案後設資料。

Ledger 也就是 Pulsar 中的 segment。

writer 寫資料時,首先會開啟一個新 Ledger,函式如下:

openLedger(組內節點數目、資料備份數目、等待刷盤節點數目)
複製程式碼

比如(5,3,2)代表組內共有 5 個 Bookie 節點,寫資料時需要寫入 3 個節點,有 2 個節點返回成功代表寫入成功。

這樣寫入的這 3 個節點資料完全一樣,關係是對等的,不存在主從關係。

資料讀寫

BookKeeper 資料讀寫如下圖:

圖片

writer 以 roundrobin 的方式寫入 bookie,比如在上圖中,第一條資料寫入 Bookie1、Bookie2 和 Bookie3,第二條資料寫入 Bookie2、Bookie3、Bookie4,第三條資料寫入 Bookie3、Bookie4、Bookie5,第四條資料寫入 Bookie4、Bookie5 和 Bookie1。

在開啟一個 Ledger 時,就傳入了 bookie 數量,這樣在寫每個 entry 時,就用 entry 的 id 跟 bookie 數量取模,來確定寫到哪幾個 bookie 上。比如第 3 條訊息跟 5 取模是 3,就寫到 Bookie3、Bookie4 和 Bookie5。

這樣以輪詢的方式將 Ledger 資料寫入各個 bookie 節點,每個 bookie 節點的資料是均衡的,每個 bookie 節點的磁碟頻寬和網路卡頻寬都能得到充分利用。

讀高可用

Reader 在讀取資料時,可以讀取多份資料中的任意一份資料。BookKeeper 會設定一個讀超時時間,如果讀取超時了,會給另外一個 bookie 節點(speculative read)傳送讀請求。

寫高可用

如果某個 bookie 節點(比如 bookie5)發生故障不能寫入了,BookKeeper 會做如下處理:

•記錄出錯的 entry id•對故障節點的資料進行封裝•關閉當前的 Ledger,重新開啟一個新的 Ledger,這個 Ledger 會重新選擇 bookie 節點,1、2、3、4、6。•如果 bookie5 恢復,就不再提供寫服務了,只提供讀服務。•如果不能恢復,就把 bookie5 的資料,從其他節點的備份中恢復到新的節點上,這個過程需要根據 Ledger id 跟 5 取模來判斷是否落到 bookie5 上,資料恢復過程並不影響 Reader,因為其他兩份資料可以繼續提供服務。

I/O 模型

BookKeeper 的 I/O 模型如下圖,這個圖是單個 bookie 的資料流轉:

圖片

整個流程入下:

•Writer 寫入的資料首先到達 Journal,Journal 將資料進行 group 後刷到到 Journal 盤,這個刷盤的資料順序跟 writer 寫入順序一致。

Writer 寫入 Journal Disk 是實時刷盤。

•Journal Disk 的資料會寫入 memory table 進行資料整理,把同一個 topic 的資料整理到一起。•把整理好的資料刷盤。Index Disk 儲存 entry 的 index,對應 entry 在 Logger Disks 的 offset。

讀寫分離

讀取資料時,首先從 Memory Cache 中讀取資料,如果資料不存在,才會去 Index Disk 和 Logger Disk 讀取資料。而寫資料是實時落盤到 Journal Disk,這樣實現了讀寫隔離。

強一致性

資料可以實時刷盤到 Journal Disk,保證了資料的強一致性。

靈活 SLA

對於寫效能要求高的業務場景,可以單獨加強 Journal 盤效能,而對於讀效能要求高的場景,可以加強 Ledger Disk 和 Index Disk 的效能。

Pulsar 中的使用

Pulsar 的架構圖如下:

圖片

每次 Producer 生成的訊息實時落盤後,給 Producer 返回一個 ACK。

Consumer 消費訊息後,還會修改 Cursor 中儲存的 offset,並且也會記錄到 BookKeeper。這樣保證了 Cursor 的一致性。

相關閱讀

為什麼選擇 Apache BookKeeper — Part 2為什麼選擇 Apache BookKeeper - Part 1

相關文章