RocketMQ高性能原理(pushConsumer,CommitLog,ZeroCopy)


1. Rocketmq消費模型(實時性)
常見的數據同步方式有這幾種:
  push:producer發送消息后,broker馬上把消息投遞給consumer。這種方式好在實時性比較高,但是會增加broker的負載;而且消費端能力不同,如果push推送過快,消費端會出現很多問題。
  pull:producer發送消息后,broker什么也不做,等着consumer自己來讀取。它的優點在於主動權在消費者端,可控性好;但是間隔時間不好設置,間隔太短浪費資源,間隔太長又會消費不及時。
  長輪詢:當consumer過來請求時,broker會保持當前連接一段時間 默認15s,如果這段時間內有消息到達,則立刻返回給consumer;15s沒消息的話則返回空然后重新請求。這種方式的缺點就是服務端要保存consumer狀態,客戶端過多會一直占用資源。

RocketMQ默認是采用pushConsumer方式消費的,從概念上來說是推送給消費者,它的本質是pull+長輪詢。這樣既通過長輪詢達到了push的實時性,又有了pull的可控性。系統收到消息后會自動處理消息和offset(消息偏移量),如果期間有新的consumer加入會自動做負載均衡(集群模式下offset存在broker中; 廣播模式下offset存在consumer里)。當然我們也可以設置為pullConsumer模式,這樣靈活性會提高,但是代碼卻會很復雜,需要手動維護offset,消息存儲和狀態。

  * offset:簡單粗暴的理解就是數組下標。message queue是無限長的數組,每次消息進來就會漲1,下標就是offset。consumer可以通過指定offse位置開始讀取數據。queue的maxOffset是消息的最大offset,不是最新消息的offset 而是最新消息的offset+1,minOffset則是現存的最小offset。

2. Rocketmq消息存儲(順序寫,隨機讀)   

  消息存儲是由ConsumeQueue和CommitLog配合完成的。一個Topic里面有多個MessageQueue,每個MessageQueue對應一個ConsumeQueue.
  默認地址:store/consumequeue/{topicName}/{queueid}/fileName
ConsumeQueue里記錄着消息物理存儲地址。(讀:consumer根據消息的consumeQueue找到消息存儲具體路徑,從而讀取里面信息)
CommitLog就存儲文件具體的字節信息。(寫:文件大小默認1g,文件名稱20位數 左邊補0右邊為偏移量。消息順序寫入文件,文件滿了則寫入下一個文件)

3. ZeroCopy高性能零拷貝 

linux有兩個上下文(內核態、用戶態), 傳統的將一個file讀取並發送出去會經歷4個過程。
 read時:
  1. 將文件從磁盤copy到kernel(內核)態
  2. cpu將kernrl態的數據copy到user(用戶)態
 write時:
  3. user態的內容會copy到kernel態的socket的buffer中
  4. 將kernel中buffer的數據copy到網卡中傳送
 我們可以發現2、3完全是多余的步驟,而且上下文之間的切換是很耗性能的。

   

  ZeroCopy:內核直接把磁盤的數據傳輸到socket,而不是通過應用程序去傳輸。減少了不必要的內核緩沖區和用戶緩沖區間的拷貝,從而提升了性能。
  零拷貝技術有mmap及sendfile;sendfile大文件傳輸快,mmap小文件傳輸快。MMQ發送的消息通常都很小,rocketmq就是以mmap+write方式實現的。像kafka、netty都采用了零拷貝技術。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM