最佳實踐|放棄 Ceph,Salesforce 使用 Apache BookKeeper 在雲中實現最強儲存

ApachePulsar發表於2021-11-17

關於 Apache Pulsar

Apache Pulsar 是 Apache 軟體基金會頂級專案,是下一代雲原生分散式訊息流平臺,集訊息、儲存、輕量化函式式計算為一體,採用計算與儲存分離架構設計,支援多租戶、持久化儲存、多機房跨區域資料複製,具有強一致性、高吞吐、低延時及高可擴充套件性等流資料儲存特性。
GitHub 地址:http://github.com/apache/pulsar/

本文要點

  • 使儲存系統感知雲的傳統方式是直接遷移,這種方式表現良好,但從我們的經驗來看,重構雲感知架構效果更好。
  • 目前,在跨區域環境中部署 Apache BookKeeper 時需要手動將儲存節點對映到特定區域 / 可用性區域,但在區域中斷時,永續性和可用性會受到影響。
  • Salesforce 獨有的使 Apache BookKeeper 感知雲的方法是通過智慧化儲存節點,讓其在雲中部署可以有效運轉,並保證永續性和可用性。
  • 這些方法簡化了叢集的改進、升級和重啟操作,對消費服務的影響最低。

在 Salesforce,我們需要可以同時處理兩種流的儲存系統:一種流用來預寫日誌,另一種流用來處理資料。但對這兩種流,我們的要求相互矛盾:預寫日誌流的寫入延遲低,而讀取吞吐量高;資料流的寫入吞吐量高,但隨機讀取延遲低。作為雲端計算的領軍企業,我們的儲存系統必須具備雲感知能力(可用性和永續性要求越來越高)。為了在商用硬體上執行並方便擴容,我們無法更改部署模型設計。

開源方案

在對儲存系統進行初步研究後,我們考慮是自己搭建一套還是購買一套。

考慮到整體規劃和上市時間、資源、成本等主要的業務驅動因素,我們決定使用開源儲存系統。

在檢視了開原始碼後,我們有兩個備選方案:Ceph 和 Apache BookKeeper。由於這套系統需要對客戶開放,可擴充套件性和一致性都很重要,系統必須完全滿足用例的 CAP(Consistency:一致性;Availability:可用性;Partition Tolerance:分割槽容錯性)要求以及我們自己的特殊需求。首先,我們來看一下 BookKeeper 和 Ceph 在 CAP 和其他方面的表現。

Ceph 可以保證一致性和分割槽容錯,讀取路徑可以藉助不可靠讀取提供可用性和分割槽容錯;但要使寫入路徑保證可用性和分割槽容錯性並不容易。並且,我們不能更改部署資料。

我們決定選擇 Apache BookKeeper。BookKeeper 支援僅追加 / 不可變資料儲存,採用高可複製的分散式日誌,滿足我們對系統 CAP 的要求。BookKeeper 還具備以下特點:

  • 已 Ack 的寫入始終可讀。
  • 已讀 Entry 始終可讀。
  • 無 Master 伺服器,客戶端使用 Apache ZooKeeper 實現共識(consensus)演算法,獲取後設資料。
  • 資料佈局無需複雜的雜湊 / 計算。

Salesforce 也一直支援開源產品,Apache BookKeeper 社群積極活躍,充滿活力。

Apache BookKeeper——近乎完美,但還有改善空間

Apache BookKeeper 幾乎實現了我們對儲存系統的全部要求,但仍需做一些工作。首先來看一下 Apache BookKeeper 可以實現我們的哪些要求。

  • 儲存節點稱為 Bookie;一組 Bookie 稱為 Ensemble。
  • 寫入的最小單元為 Entry,Entry 不可更改。
  • 一組 Entry 稱為 Ledger,Ledger 僅可追加,不可更改。
  • 寫入或複製 Bookie 的數量稱為 Write Quorum——Entry 的最大副本數。
  • 確認寫入前 Bookie 的數量稱為 Ack quorum——Entry 的最小副本數。

從永續性來看,Ledger 跨 Bookie Ensemble 複製,Ledger 內的 Entry 可以跨 Ensemble。

Ensemble Size: 5 Write Quorum Size: 3 Ack Quorum Size: 2

寫入根據 Write Quorum 和 Ack Quorum(可配置)進行確認,從而保證低寫入延遲和高可擴充套件。

但實際上,在雲中的商用硬體上執行 BookKeeper 並不輕鬆。

資料佈局策略不具備雲感知能力,並且沒有顧及底層雲服務提供商(雲基礎設施)。目前,一些使用者的部署方法是手動標識不同可用性區域中的節點,並進行邏輯分組,然後以組為單位改進資料佈局策略。這不失為一種解決方案,但不支援區域故障,也降低了維護和升級大型叢集時系統的易用性。

另外,所有云基礎設施的可用區域裡都出現過停機情況;而一般的理解是,應用程式要針對這些故障做相應的設計。一個很好的例子是,2012 年聖誕節期間,Amazon 網路服務可用區域故障,Netflix 底層所依賴的公有云基礎設施停機,而 Netflix 服務仍然可以在有限的容量上執行。

公有云中的問題

公有云基礎設施易於擴充套件,在一定程度上降低了使用和維護的成本,因此,從網站到應用程式,甚至是企業級軟體,基本都在公有云服務提供商提供的基礎設施上執行。但是,公有云也有其缺陷,它在節點、區域或地區層面都可能出現不可用的情況。底層基礎設施不可用,使用者什麼都做不了。起因可能是某些機器、區域或地區出現故障,也可能是由硬體故障引起的網路延遲增加。所以最終當在公有云基礎設施上執行應用程式時,開發人員在設計時需要考慮由故障引發的問題。

Apache BookKeeper 本身不能解決這一問題,因此,我們需要自行設計一個修復程式。

Salesforce 重構

對問題有了一定的瞭解之後,我們開始考慮解決方案,讓 BookKeeper 具備雲感知能力,滿足我們的以下要求。

  • 在公有云叢集中的 Bookie 需要一個標識。
  • 根據可用區域內 Ensemble 的分佈設計資料佈局策略,實現更好的高可用,簡化維護和部署。
  • 改進 Bookie 已有的功能,如讀取、寫入、資料複製等,使 Bookie 可以充分利用多區域佈局的優勢,並計算跨區域傳輸資料的成本。
  • 上述工作和雲基礎設施無關。

我們的解決方案如下:

雲感知能力:Cookie 和 Kubernetes

現有的 BookKeeper 架構為所有 Bookie 提供唯一標識(在首次啟動時分配)。標識儲存在後設資料儲存(ZooKeeper)中,其他 Bookie 或客戶端可以訪問。

使 Apache BookKeeper 具有云感知能力的第一步是讓所有 Bookie 均可獲取它部署在 Kubernetes 叢集中的位置。我們認為 Cookie 資料是獲取位置資訊的最佳方式。

因此,我們在 Cookie 中增加了 networkLocation 欄位,它包含兩部分:可用區域和升級域,用於定位 Bookie。Kubernetes 和雲基礎設施無關,我們可以使用 Kubernetes API 來查詢底層的可用區域資訊。我們還根據涉及主機名順序索引的公式生成了 upgradeDomain 欄位。它可以用來滾動升級,而不影響叢集的可用性。

在機器啟動時生成上述欄位和對應值,並儲存在後設資料儲存中供使用者訪問。這些資訊可以用於生成 Ensemble,分配 Bookie 到 Ensemble,以及確定從哪些 Bookie 複製資料,複製的資料儲存到哪些 Bookie。

公有云佈局策略

現在,客戶端已經足夠智慧,可以與某些區域中的 Bookie 進行通訊,下一步便是確保有一個可以使用這一資訊的資料佈局策略。我們開發了 ZoneAwareEnsemblePlacementPolicy(ZEPP)。這是一個針對基於雲部署而設計的兩級層次化佈局策略。ZEPP 可以獲取可用區(AZ)和 upgradeDomains(UD)資訊。

AZ 是區域內隔離資料中心的邏輯概念;UD 是 AZ 內的一組節點,關閉 UD 不會影響服務,UD 還可以監測到區域的關閉和重啟。

下圖為 ZEPP 可採用的一種部署示意圖。這種部署方式兼顧了 Cookie 中的 AZ 和 UD 資訊,並據此對 Bookie 節點進行分組。

可用性 & 延遲 & 成本

進行上述調整後,Apache BookKeeper 可以具備雲感知能力了。但成本也是設計架構時必須考慮的因素之一。大多數雲基礎設施對傳出服務的資料進行單向收費,跨可用區傳輸的費用會有所不同。這是 BookKeeper 客戶端需要考慮的一個重要因素,因為它現在是從 Ensemble 中隨機選擇一個 Bookie 進行讀取。

如果 Bookie 和客戶端屬於不同的可用區,會增加不必要的成本。資料複製可能發生在跨可用區的 Bookie 之間,當可用區出現故障時,使用成本會增加。

我們通過以下方式來處理這些特殊情況:

重排序讀取

目前,BookKeeper 客戶端從 Ensemble 隨機選取 Bookie 進行讀取。藉助重排序讀取特性,現在客戶端可以選擇 Bookie,從而減小讀延遲,降低成本。

啟用重排序讀取後,客戶端按照以下順序選擇 Bookie:

  • 本地區域中滿足要求且待處理請求少的 Bookie;
  • 遠端區域中滿足要求且待處理請求少的 Bookie;
  • 本地區域中故障最少或待處理請求高於設定閾值的下一個 Bookie;
  • 遠端區域中故障最少或待處理請求高於設定閾值的下一個 Bookie。

按照上述順序,執行很長時間且出現過故障的系統也可以滿足我們對延遲與成本的要求。

處理區域故障

當區域關閉時,不同 Ensemble 中的所有 Bookie 都開始將資料複製到當前可用區域內的 Bookie 中,從而滿足 Ensemble Size 和 Quorum 要求,引起“驚群問題”。

要解決這一問題,首先要確定區域關閉的時間。故障可能是暫時性的操作失誤,比如網路故障引起區域不可用,我們不希望系統複製 TB 級的資料;但同時我們也要做好準備,應對真正的故障。我們的解決方案包含兩步:

  • 辨別區域是真正故障還是暫時故障;
  • 將整個區域的大規模自動複製轉換為手動操作。

下圖為區域關閉與重啟時我們的應對方案。

根據區域中可用 Bookie 數量和區域中 Bookie 總量可以計算出 HighWaterMark 和 LowWaterMark 的值。使用者可以為這兩個值設定閾值,系統可以據此判斷故障情況,進而確定故障型別。

當區域標記為關閉時,我們會禁用自動複製,從而避免跨區域自動複製 TB 級的資料。此外,我們在資料複製的地方增加了告警,提示使用者可能出現的區域故障。我們認為,運維專家能夠將噪聲與實際故障區分開,並決定是否開始自動複製整個區域的資料。

我們還可以通過 shell 命令啟動已禁用的 Bookie 自動複製。

我們的收穫

Apache BookKeeper 是一個開源專案,社群非常活躍,並一直在積極討論面臨的一系列挑戰。由於BookKeeper 是儲存資料的元件,對很多使用者而言,其雲感知能力十分重要。

本文介紹的更改已在 Salesforce 進行了實戰驗證。目前,藉助 Apache BookKeeper ,我們已經可以支援 AZ 和 AZ + 1 故障。但是,這樣的架構更改必然會影響到可用性、延遲、成本、部署和維護的簡易性。社群已經接受了我們提交的一些更改,我們會繼續為社群做出貢獻。我們希望這些更改可以簡化叢集打補丁、升級、重啟的操作,同時儘可能降低對消費服務的影響。

關於作者

Anup Ghatage 任職於 Salesforce,主要負責雲基礎架構和資料工程,曾任職於 SAP 和 Cisco Systems,對維護和開發高可擴充套件的系統有濃厚興趣。他本科畢業於普納大學計算機專業,碩士畢業於卡耐基·梅隆大學。他是 Apache BookKeeper 的 committer,積極參與 Apache BookKeeper 的開發。歡迎在 Twitter 上關注 Anup(@ghatageanup )。

相關閱讀

點選 連結 ,檢視英文版原文。

相關文章