在雙十一程序中投入同樣的硬體資源,Kafka 搭建的日志集群單個Topic可以達到幾百萬的TPS,而使用RocketMQ組件的核心業務集群,集群TPS只能達到幾十萬TPS,這樣的現象激發了我對兩者性能方面的思考,
溫馨提示:TPS只是眾多性能指標中的一個,我們在做技術選型方面要從多方面考慮,本文并不打算就訊息中間件選型方面投入太多筆墨,重點想嘗試剖析兩者在性能方面的設計思想,
1、檔案布局
1.1 Kafka 檔案布局
Kafka 檔案在宏觀上的布局如下圖所示:

正如上圖所示,Kafka 檔案布局的主要特征如下:
檔案的組織以 topic + 磁區進行組織,每一個 topic 可以創建多個磁區,每一個磁區包含單獨的檔案夾,并且是多副本機制,即 topic 的每一個磁區會有 Leader 與 Follow,并且 Kafka 內部有機制保證 topic 的某一個磁區的 Leader 與 follow 不會存在在同一臺機器,并且每一臺 broker 會盡量均衡的承擔各個磁區的 Leader,當然在運行程序中如果不均衡,可以執行命令進行手動重平衡,Leader 節點承擔一個磁區的讀寫,follow 節點只負責資料備份,
Kafka 的負載均衡主要依靠磁區 Leader 節點的分布情況,
磁區的 Leader 節點負責讀寫,而從節點負責資料同步,如果Leader磁區所在的Broker節點發生宕機,會觸發主從節點的切換,會在剩下的 follow 節點中選舉一個新的 Leader 節點,其資料的流入流程如下圖所示:

磁區 Leader 收到客戶端的訊息發送請求時,是寫入到 Leader 節點后就回傳還是要等到它的從節點全部寫入后再回傳,這里非常關鍵,會直接影響訊息發送端的時延,故 Kafka 提供了 ack 這個引數來進行策略選擇:
-
ack = 0
不等broker端確認就直接回傳,即客戶端將訊息發送到網路中就回傳發送成功,
-
ack = 1
Leader 節點接受并存盤后向客戶端回傳成功,
-
ack = -1
Leader節點和所有的Follow節點接受并成功存盤再向客戶端回傳成功,
1.2 RocketMQ 檔案布局
RocketMQ 的檔案布局如下圖所示:

RocketMQ 所有主題的訊息都會寫入到 commitlog 檔案中,然后基于 commitlog 檔案構建訊息消費佇列檔案(Consumequeue),訊息消費佇列的組織結構按照 /topic/{queue} 進行組織,從集群的視角來看如下圖所示:

RocketMQ 默認采取的是主從同步,當然從RocketMQ4.5引入了多副本機制,但其副本的粒度為 Commitlog 檔案,上圖中不同 master 節點之間的資料完成不一樣(資料分片),而主從節點節點資料一致,
1.3 檔案布局對比
Kafka 中檔案的布局是以 Topic/partition ,每一個磁區一個物理檔案夾,在磁區檔案級別實作檔案順序寫,如果一個Kafka集群中擁有成百上千個主題,每一個主題擁有上百個磁區,訊息在高并發寫入時,其IO操作就會顯得零散,其操作相當于隨機IO,即 Kafka 在訊息寫入時的IO性能會隨著 topic 、磁區數量的增長,其寫入性能會先上升,然后下降,
而 RocketMQ在訊息寫入時追求極致的順序寫,所有的訊息不分主題一律順序寫入 commitlog 檔案,并不會隨著 topic 和 磁區數量的增加而影響其順序性,但通過筆者的實踐來看一臺物理機并使用SSD盤,但一個檔案無法充分利用磁盤IO的性能,
兩者檔案組織方式,除了在磁盤的順序寫方面有所區別后,由于其粒度的問題,Kafka 的 topic 擴容磁區會涉及磁區在各個 Broker 的移動,其擴容操作比較重,而 RocketMQ 資料存盤是基于 commitlog 檔案的,擴容時不會產生資料移動,只會對新的資料產生影響,RocketMQ 的運維成本對 Kafka 更低,
最后 Kafka 的 ack 引數可以類比 RocketMQ 的同步復制、異步復制,
Kafka 的 ack 引數為 1 時,對比 RocketMQ 的異步復制; -1 對標 RocketMQ 的 同步復制,而 -1 則對標 RocketMQ 訊息發送方式的 oneway 模式,
2、資料寫入方式
2.1 Kafka 訊息寫入方式
Kafka 的訊息寫入使用的是 FileChannel,其代碼截圖如下:

并且在訊息寫入時使用了 transferTo 方法,根據網上的資料說 NIO 中網路讀寫真正是零拷貝的就是需要呼叫 FileChannel 的 transferTo或者 transferFrom 方法,其內部機制是利用了 sendfile 系統呼叫,
2.2 RocketMQ 訊息寫入方式
RocketMQ 的訊息寫入支持 記憶體映射 與 FileChannel 寫入兩種方式, 示例如下圖所示:

2.3 訊息寫入方式對比
盡管 RocketMQ 與 Kafka 都支持 FileChannel 方式寫入,但 RocketMQ 基于 FileChannel 寫入時呼叫的 API 卻并不是 transferTo,而是先呼叫 writer,然后定時 flush 刷寫到磁盤,其代碼截圖如下:

為什么 RocketMQ 不呼叫 transerTo 方法呢,個人覺得和 RocketMQ 需要在 Broker 組裝 MQ 訊息格式有關,需要從網路中解碼請求,傳輸到堆記憶體,然后對訊息進行加工,最終持久化到磁盤相關,
從網上查詢資料中大概傾向于這樣一個 觀點:sendfile 系統呼叫相比記憶體映射多了一次從用戶快取區拷貝到內核快取區,但對于超過64K的記憶體寫入時往往 sendfile 的性能更高,可能是由于 sendfile 是基于塊記憶體的,
3、訊息發送方式
3.1 Kafka 訊息發送機制
Kafka 在訊息發送客戶端采用了一個雙端佇列,引入了批處理思想,其訊息發送機制如下圖所示:

客戶端通過呼叫 kafka 的訊息發送者發送訊息時,訊息會首先存入到一個雙端佇列中,雙端佇列中單個元素為 ProducerBatch,表示一個發送批次,其最大大小受引數 batch.size 控制,默認為 16K,然后會單獨開一個 Send 執行緒,從雙端佇列中獲取一個發送批次,將訊息按批發送到 Kafka集群中,這里引入了 linger.ms 引數來控制 Send 執行緒的發送行為,
為了提高 kafka 訊息發送的高吞吐量,即控制在快取區中未積滿 batch.size 時來控制訊息發送執行緒的行為,是立即發送還是等待一定時間,如果linger.ms 設定為 0表示立即發送,如果設定為大于0,則訊息發送執行緒會等待這個值后才會向broker發送, linger.ms 引數者會增加回應時間,但有利于增加吞吐量,有點類似于 TCP 領域的 Nagle 演算法,
Kafka 的訊息發送,在寫入 ProducerBatch 時會按照訊息存盤協議組織好資料,在服務端可以直接寫入到檔案中,
3.2 RocketMQ 訊息發送機制
RocketMQ 訊息發送在客戶端主要是根據路由選擇演算法選擇一個佇列,然后將訊息發送到服務端,訊息會在服務端按照訊息的存盤格式進行組織,然后進行持久化等操作,
3.3 訊息發送對比
Kafka 在訊息發送方面比 RokcetMQ 有一個顯著的優勢就是訊息格式的組織是發生在客戶端,這樣會有一個大的優勢節約了 Broker 端的CPU壓力,客戶端“分布式”的承接了其優勢,其架構方式有點類似 shardingjdbc 與 MyCat 的區別,
Kafka 在訊息發送端另外一個特點是引入了雙端快取佇列,Kafka 無處不在追求批處理,這樣顯著的特點是能提高訊息發送的吞吐量,但與之帶來的是增大訊息的回應時間,并且帶來了訊息丟失的可能性,因為 Kafka 追加到訊息快取后會回傳成功,如果訊息發送方例外退出,會帶來訊息丟失,
Kafka 中的 linger.ms = 0 可類比 RocketMQ 訊息發送的效果,
但 Kafka 通過提供 batch.size 與 linger.ms 兩個引數按照場景進行定制化,比 RocketMQ 靈活,
例如日志集群,通常會調大 batch.size 與 linger.ms 引數,重復發揮訊息批量發送機制,提高其吞吐量;但如果對一些回應時間比較敏感的話,可以適當減少 linger.ms 的值,
4、總結
從上面的對比來看,Kafka 在性能上綜合表現確實要比 RocketMQ 更加的優秀,但在訊息選型程序中,我們不僅僅要參考其性能,還有從功能性上來考慮,例如 RocketMQ 提供了豐富的訊息檢索功能、事務訊息、訊息消費重試、定時訊息等,
筆者個人認為通常在大資料、流式處理場景基本選用 Kafka,業務處理相關選擇 RocketMQ,
好了,本文就介紹到這里了,您的點贊與轉發是對我持續輸出高質量文章最大的鼓勵,
歡迎加筆者微信號(dingwpmz),拉您如技術交流加群探討,筆者優質專欄目錄:
1、原始碼分析RocketMQ專欄(40篇+)
2、原始碼分析Sentinel專欄(12篇+)
3、原始碼分析Dubbo專欄(28篇+)
4、原始碼分析Mybatis專欄
5、原始碼分析Netty專欄(18篇+)
6、原始碼分析JUC專欄
7、原始碼分析Elasticjob專欄
8、Elasticsearch專欄(20篇+)
9、原始碼分析MyCat專欄
10、原始碼分析 Canal
CSDN認證博客專家
RocketMQ
資深架構師
中間件興愛好者
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/229133.html
標籤:其他
上一篇:2015到2020JAVA架構技術演進,阿里架構師到底有多牛逼?
下一篇:本人香樟精英經驗分享會部分經驗
