Apache BookKeeper:一種面向Apache Pulsar的合格的存儲(chǔ)系統(tǒng)
譯文?譯者 | 布加迪
審校 | 孫淑娟
如果您熟悉Kafka和RocketMQ等消息系統(tǒng),可能知道服務(wù)通常與其架構(gòu)中的存儲(chǔ)密切相關(guān)。與它們不同的是,Apache Pulsar在設(shè)計(jì)時(shí)采用了將存儲(chǔ)與計(jì)算分開(kāi)的兩層架構(gòu),這實(shí)際上在其無(wú)狀態(tài)代理上進(jìn)行。Pulsar依賴Apache BookKeeper服務(wù)器(又叫bookies)進(jìn)行持久存儲(chǔ)。本文側(cè)重介紹BookKeeper基礎(chǔ)知識(shí),表明它如何為所處理的數(shù)據(jù)實(shí)現(xiàn)高可用性。
圖1
Apache BookKeeper簡(jiǎn)介
BookKeeper最初在雅虎開(kāi)發(fā),代表了一種可靠的高性能存儲(chǔ)系統(tǒng)。它提供分布式可擴(kuò)展的存儲(chǔ)服務(wù),具有低延遲和強(qiáng)容錯(cuò)性的優(yōu)點(diǎn)。這些充分說(shuō)明了為什么它能夠充當(dāng)Pulsar的存儲(chǔ)層。BookKeeper將數(shù)據(jù)存儲(chǔ)在分類帳(ledger)中,分類帳只能追加且不可變。借助特殊的復(fù)制協(xié)議,BookKeeper以并發(fā)方式在多個(gè)節(jié)點(diǎn)上安全地存儲(chǔ)日志條目,因而具有高可用性。
顧名思義,BookKeeper和分類帳在云原生環(huán)境中大有用途。不妨設(shè)想一下簿記員使用分類帳記錄所有相關(guān)賬戶信息,以跟蹤企業(yè)的財(cái)務(wù)狀況。
Apache BookKeeper中的關(guān)鍵概念
為了更好地了解BookKeeper如何存儲(chǔ)數(shù)據(jù),不妨先看一下幾個(gè)基本概念。
- Bookie
Bookie是BookKeeper中的存儲(chǔ)服務(wù)器或節(jié)點(diǎn),彼此同等。BookKeeper強(qiáng)大的動(dòng)態(tài)擴(kuò)展功能(尤其是在容器化環(huán)境中)歸功于無(wú)主節(jié)點(diǎn)(leaderless)設(shè)計(jì)。
- Ensemble
用于存儲(chǔ)分類帳條目的可用bookie的集合,即寫(xiě)入條目的節(jié)點(diǎn)。當(dāng)一個(gè)bookie失效時(shí),處理寫(xiě)入它的客戶端將換成一個(gè)新的bookie,這名為“ensemble change”。在Pulsar的計(jì)算存儲(chǔ)分離架構(gòu)中,客戶端應(yīng)用程序不需要關(guān)心存儲(chǔ)層中實(shí)際發(fā)生的事情。
- 分類帳
分類帳是BookKeeper中的基本存儲(chǔ)單元,在Pulsar中又叫Segment。BookKeeper客戶端負(fù)責(zé)創(chuàng)建和刪除分類帳,并從分類帳中讀取條目。滿足某些條件時(shí)(比如條目數(shù)或壽命達(dá)到預(yù)設(shè)閾值),分類帳將被關(guān)閉,之后再無(wú)法向其寫(xiě)入數(shù)據(jù),只允許讀取。任何客戶端都可以創(chuàng)建分類帳。理想情況下,創(chuàng)建分類帳的所有者客戶端應(yīng)該是關(guān)閉它的客戶端。一旦關(guān)閉,分類帳不可變。分類帳是最小的刪除單位,這意味著您只能刪除整個(gè)分類帳,而不能刪除分類帳中的單個(gè)條目。
除了用于存儲(chǔ)普通消息的分類帳外,BookKeeper還有一種特殊的分類帳,即游標(biāo)分類帳。游標(biāo)為Pulsar中的消息消費(fèi)和確認(rèn)提供跟蹤機(jī)制。每個(gè)訂閱都有一個(gè)與之關(guān)聯(lián)的游標(biāo),游標(biāo)存儲(chǔ)消息消費(fèi)和確認(rèn)的位置信息。消費(fèi)者可能根據(jù)訂閱類型來(lái)共享同樣的游標(biāo)。我們?cè)谶@里不詳細(xì)介紹這個(gè)話題。我們只需知道Pulsar在BookKeeper中為每個(gè)訂閱維護(hù)一個(gè)分類帳。在消費(fèi)者處理消息(向代理發(fā)送確認(rèn))、代理收到確認(rèn)之后,代理隨后相應(yīng)地更新游標(biāo)分類帳。更具體地說(shuō),Pulsar定期匯總綁定到同一訂閱的所有消費(fèi)者的所有確認(rèn)信息作為條目,并將其寫(xiě)入bookie。這個(gè)過(guò)程與編寫(xiě)普通消息基本相同。
- 片段
片段在bookie的分類帳中存儲(chǔ)連續(xù)序列的條目。分類帳可能含有一個(gè)或多個(gè)片段。作為BookKeeper中最小的分布單元,單個(gè)分類帳的片段可以分散在不同的bookie中。這意味著嚴(yán)格來(lái)講,存儲(chǔ)在單個(gè)bookie的數(shù)據(jù)是分類帳的片段。對(duì)于單個(gè)片段而言,如果寫(xiě)入 bookie失敗,會(huì)選擇新的bookie進(jìn)行寫(xiě)入(即上面提到的“ensemble change”)。結(jié)果,將在bookie上創(chuàng)建新片段。請(qǐng)注意,這兩個(gè)片段屬于同一個(gè)分類帳,但屬于不同的ensemble。
- 條目
條目含有寫(xiě)入分類帳的實(shí)際數(shù)據(jù)。每個(gè)分類帳可能含有不同數(shù)量的條目。每個(gè)條目都有條目ID作為其在分類帳中的唯一標(biāo)識(shí)符。
- 消息
消息是存儲(chǔ)在條目中的特定信息。消息可以分為兩種:?jiǎn)螚l消息和批量消息。
批量消息本質(zhì)上是一系列單條消息。在客戶端啟用消息批處理后,消息將在從生產(chǎn)者發(fā)送到代理之前作為一個(gè)整體進(jìn)行分組。Brokers然后調(diào)用BookKeeper客戶端,將批量消息寫(xiě)入bookie。當(dāng)消費(fèi)者從代理讀取消息時(shí),代理將批量消息分發(fā)給它們。請(qǐng)注意,批量消息在客戶端合并和拆分。您可以使用batchingMaxPublishDelay(批量處理待發(fā)送消息的時(shí)間段)和batchingMaxMessages(批量消息中的最大消息數(shù))等參數(shù),為生產(chǎn)者定制批量消息配置。
注意:每個(gè)條目可能包含一條或多條消息。如果禁用消息批量處理,一個(gè)條目?jī)H存儲(chǔ)一條消息。
圖2
視用例而定,您可以選擇啟用或禁用消息批量處理。與大多數(shù)分布式消息系統(tǒng)不同,Pulsar支持消息隊(duì)列和流傳輸。在消息隊(duì)列場(chǎng)景中,高吞吐量通常不是必須的,因此很少在客戶端啟用消息批量處理。相比之下,在流傳輸情形下,消息的生成速度要快得多,這需要批量處理,以便生產(chǎn)者可以將消息作為更大的包來(lái)發(fā)送。
數(shù)據(jù)高可用性
為了保證數(shù)據(jù)的高可用性,BookKeeper采用了一種仲裁機(jī)制向bookie并行寫(xiě)入數(shù)據(jù)。具體來(lái)說(shuō),我們可以為要?jiǎng)?chuàng)建的新分類帳定義以下三個(gè)關(guān)鍵整數(shù):
- Ensemble Size(E):寫(xiě)入存儲(chǔ)在分類帳中的消息的可用bookie的數(shù)量。
- Write Quorum(WQ):要寫(xiě)入的消息的副本,或同時(shí)保存條目(或其所屬片段)的bookie的數(shù)量。WQ可以等于或小于E,但不能小于1或AQ。
- Ack Quorum(AQ):在寫(xiě)入成功之前,代理需要接收的確認(rèn)數(shù)量。如果達(dá)到這個(gè)值,代理將向客戶端發(fā)回確認(rèn)信息。否則,寫(xiě)入失敗。
這三個(gè)參數(shù)可以分別在代理、命名空間和主題級(jí)別進(jìn)行配置。比如在代理級(jí)別,編輯Pulsar包的conf目錄中的broker.conf文件,并設(shè)置所需的值:
屬性文件 # Number of bookies to use when creating a ledger managedLedgerDefaultEnsembleSize=2 # Number of copies to store for each message managedLedgerDefaultWriteQuorum=2 # Number of guaranteed copies (acks to wait before a write is complete) managedLedgerDefaultAckQuorum=2 |
注意:我們可以根據(jù)對(duì)一致性的需求來(lái)配置以上參數(shù)。比如說(shuō),WQ=AQ表示最高級(jí)別的一致性。在這種情況下,消息只有在收到所有副本的確認(rèn)后才能成功持久化。當(dāng)AQ比較小(比如AQ = 1)時(shí),延遲會(huì)較低,但是數(shù)據(jù)丟失風(fēng)險(xiǎn)較大。一般來(lái)說(shuō),最好設(shè)置AQ ≥ (WQ + 1)/2。
比如在下圖中,我們?cè)O(shè)置E = 5、WQ = 3和AQ = 2。這意味著:
- 5個(gè)bookie可用于將數(shù)據(jù)存儲(chǔ)在分類帳中。
- 一個(gè)條目的3個(gè)副本存儲(chǔ)在3個(gè)不同的bookie上。
- 收到來(lái)自2個(gè)bookie的確認(rèn)時(shí),表示條目寫(xiě)入成功。
圖3
數(shù)據(jù)使用循環(huán)分布寫(xiě)入bookie。這么設(shè)計(jì)是由于,它可以充分利用池中所有bookie的處理能力。如下所示,Entry 1寫(xiě)入Bookie 1、Bookie 2和Bookie 3,Entry 2寫(xiě)入Bookie 2、Bookie 3和Bookie 4,以此類推。
圖4
循環(huán)方法提供了一種簡(jiǎn)單的方法來(lái)快速找出通過(guò)條目ID來(lái)存儲(chǔ)特定條目副本的bookie。比如說(shuō),我們知道條目2在Bookie 2、Bookie 3和Bookie 4上復(fù)制。2 mod 5等于 2,這意味著對(duì)于特定的條目X而言,如果X mod 5等于2,條目X就存儲(chǔ)在Bookie 2上、Bookie 3和Bookie 4上,比如條目 7 (X=7)。
使用Apache BookKeeper
當(dāng)您安裝Pulsar集群時(shí),BookKeeper將一同部署。如果您想運(yùn)行BookKeeper,不需要單獨(dú)下載其代碼。相反,下載Pulsar并在bin目錄中運(yùn)行./pulsar-daemon start bookie命令。如果您使用Pulsar社區(qū)提供的Helm chart將其安裝在Kubernetes集群上,bookie Pods則部署在StatefulSet 中。
結(jié)語(yǔ)
本文介紹了BookKeeper的基礎(chǔ)知識(shí),分析了如何將數(shù)據(jù)寫(xiě)入bookie以實(shí)現(xiàn)高可用性。我們可以將BookKeeper簡(jiǎn)單地視為一個(gè)數(shù)據(jù)庫(kù),因?yàn)樗话魏螛I(yè)務(wù)邏輯。該開(kāi)源工具具有出色的可擴(kuò)展性、強(qiáng)大的容錯(cuò)性和低延遲,具備成為合格的云原生存儲(chǔ)系統(tǒng)所需的特性,為Pulsar的獨(dú)特架構(gòu)提供了堅(jiān)實(shí)的支持。
原文標(biāo)題:??Apache BookKeeper: What Makes A Qualified Storage System for Apache Pulsar??,作者:Sherlock Xu