下一代分散式訊息佇列Apache Pulsar從入門到實現

趙鈺瑩發表於2018-07-30

Pulsar簡介

Apache Pulsar是一個企業級的分散式訊息系統,最初由Yahoo開發並在2016年開源,目前正在Apache基金會下孵化。Plusar已經在Yahoo的生產環境使用了三年多,主要服務於Mail、Finance、Sports、 Flickr、 the Gemini Ads platform、 Sherpa以及Yahoo的KV儲存。

Pulsar之所以能夠稱為下一代訊息佇列,主要是因為以下特性:

  • 線性擴充套件。能夠絲滑的擴容到成百上千個節點(Kafka擴容需要佔用很多系統資源在節點間拷貝資料,而Plusar完全不用)

  • 高吞吐。已經在Yahoo的生產環境中經受了考驗,每秒數百萬訊息

  • 低延遲。在大規模的訊息量下依然能夠保持低延遲(< 5ms)

  • 持久化機制。Plusar的持久化機制構建在Apache BookKeeper之上,提供了寫與讀之前的IO隔離

  • 基於地理位置的複製。Plusar將多地域/可用區的複製作為首要特性支援。使用者只需配置好可用區,訊息就會被源源不斷的複製到其他可用區。當某一個可用區掛掉或者發生網路分割槽,plusar會在之後不斷的重試。

  • 部署方式的多樣化。既可以執行在裸機,也支援目前例如Docker、K8S的一些容器化方案以及不同的雲廠商,同時在本地開發時也只需要一行命令即可啟動整個環境。

  • Topic支援多種消費模式:exclusive、shared、failover

架構概述

從最上層來看,一個Plusar單元由若干個叢集組成,單元內的叢集可以互相之前複製資料, plusar中通常有以下幾種元件:

  • Broker:負責處理Producer發來的訊息並分發給消費者。通過一個全域性的ZK叢集來處理多種協作式任務,例如說基於地理位置的複製。並將訊息儲存到BookKeeper中,同時單個叢集內也需要有一套ZK叢集,來儲存一些後設資料。

  • BookKeeper叢集: 內部包含多個bookies,用於持久化訊息。

  • ZooKeeper集

Broker

在Kafka和RocketMQ中,Broker負責訊息資料的儲存以及consumer消費位移的儲存等,而Plusar中的broker和他們兩個有所不同,plusar中的broker是一個無狀態的節點,主要負責三件事情:

  • 暴露REST介面用於執行管理員的命令以及topic所有者的查詢等

  • 一個用於節點間通訊的非同步的TCP伺服器,協議目前採用的是Google之前開源的Protocol Buffer

  • 為了支援地域複製,broker會將自己 叢集所在的訊息釋出到其他可用區。

訊息會被先發布到BookKeeper中,然後會在Broker本地記憶體中快取一份,因此一般來說訊息的讀取都會從從記憶體中讀取,因此第一條中所說的查詢topic所有者就是說,因為BookKeeper中的一個ledger只允許一個writer,因此我們可以呼叫rest介面獲取到某一個topic當前的所有者。

BookKeeper

BookKeeper是一個可橫向擴充套件的、錯誤容忍的、低延遲的分散式儲存服務,BookKeeper中最基本的單位是記錄,實際上就一個位元組陣列,而記錄的陣列稱之為ledger,BK會將記錄複製到多個bookies,儲存ledger的節點叫做bookies,從而獲得更高的可用性和錯誤容忍性。從設計階段BK就考慮到了各種故障,Bookies可以當機、丟資料、髒資料,但是主要整個叢集中有足夠的Bookies服務的行為就是正確的。
在Pulsar中,每個分割槽topic是由若干個ledger組成的,而ledger是一個append-only的資料結構,只允許單個writer,ledger中的每條記錄會被複制到多個bookies中,一個ledger被關閉後(例如broker當機了或者達到了一定的大小)就只支援讀取,而當ledger中的資料不再需要的時候(例如所有的消費者都已經消費了這個ledger中的訊息)就會被刪除。


Bookkeeper的主要優勢在於它可以保證在出現故障時在ledger的讀取一致性。因為ledger只能被同時被一個writer寫入,因為沒有競爭,BK可以更高效的實現寫入。在Broker當機後重啟時,Plusar會啟動一個恢復的操作,從ZK中讀取最後一個寫入的Ledger並讀取最後一個已提交的記錄,然後所有的消費者也都被保證能看到同樣的內容。

我們知道Kafka在0.8版本之前是將消費進度儲存到ZK中的,但是ZK本質上基於單個日誌的中心服務,簡單來講,ZK的效能不會隨著你增加更多的節點而線性增加,會只會相反減少,因為更多的節點意味著需要將日誌同步到更多的節點,效能也會隨之下降,因此QPS也會受單機效能影響,因此0.8版本之後就將消費進度儲存到了Kafka的Topic中,而RocketMQ最初的版本也類似,有幾種不同的實現例如ZK、資料庫等,目前版本採用的是儲存到本機檔案系統中,而Plusar採用了和Kafka類似的思想,Plusar將消費進度也儲存到了BK的ledger中。

後設資料

Plusar中的後設資料主要儲存到ZK中,例如不同可用區相關的配置會存在全域性的ZK中,叢集內部的ZK用於儲存例如某個topic的資料寫入到了那些Ledger、Broker目前的一些埋點資料等等。

Plusar核心概念

Topic

釋出訂閱系統中最核心的概念是topic,簡單來說,topic可以理解為一個管道,producer可以往這個管道丟訊息,consumer可以從這個管道的另一端讀取訊息,但是這裡可以有多個consumer同時從這個管道讀取訊息。

每個topic可以劃分為多個分割槽,同一個topic下的不同分割槽所包含的訊息都是不同的。每個訊息在被新增到一個分割槽後都會分配一個唯一的offset,在同一個分割槽內訊息是有序的,因此客戶端可以根據比如說使用者ID進行一個雜湊取模從而使得整個使用者的訊息都發往整個分割槽,從而一定程度上避免race condition的問題。
通過分割槽,將大量的訊息分散到不同的節點處理從而獲得高吞吐。預設情況下,plusar的topic都是非分割槽的,但是支援通過cli或者介面建立一定分割槽數目的topic。

預設情況下Plusar會自動均衡Producer和Consumer,但有時候客戶端想要根據自己的業務規則也進行路由,Plusar預設支援以下幾種規則:單分割槽、輪詢、雜湊、自定義(即自己實現相關介面來定製路由規則)

消費模式

消費決定了訊息具體是如何被分發到消費者的,Plusar支援幾種不同的消費模式: exclusive、shared、failover。圖示如下:

  • Exclusive: 一個topic只能被一個消費者消費。Plusar預設就是這個模式

  • Shared: 共享模式或者叫輪詢模式,多個消費者可以連線到同一個topic,訊息被依次分發給消費者,當一個消費者當機或者主動斷開連線,那麼發到那個消費者的還沒有ack的訊息會得到重新排程分發給其他消費者。

  • Failover: 多個消費者可以連線同一個topic並按照字典序排序,第一個消費者會開始消費訊息,稱之為master,當master斷開連線,所有未ack和佇列中剩下的訊息會分發給另一個消費者。

Plusar目前也支援另一種Reader介面,支援傳入一個訊息ID,例如說Message.Earliest來從最早的訊息開始消費。

總結

Plusar作為下一代分散式訊息佇列,擁有非常多吸引人的特性,也彌補了一些其他競品的短板,例如地域複製、多租戶、擴充套件性、讀寫隔離等等。


【原文連結:https://github.com/aCoder2013/blog/issues/23,作者:SongWang】


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31077337/viewspace-2168643/,如需轉載,請註明出處,否則將追究法律責任。

相關文章