RocketMQ 消息偏移量 Offset 和 CommitLog


消息偏移量 Offset

概念

  • message queue 是無限長的數組,一條消息進來下標就會漲1,下標就是 offset,消息在某個 MessageQueue 里的位置,通過 offset 的值可以定位到這條消息,或者指示 Consumer 從這條消息開始向后處理。
  • message queue 中的 maxOffset 表示消息的最大 offset,maxOffset 並不是最新的那條消息的 offset,而是最新消息的 offset+1,minOffset 則是現存在的最小 offset。
  • fileReserveTime=48 默認消息存儲48小時后,消費會被物理地從磁盤刪除,message queue 的 minOffset 也就對應增長。所以比 minOffset 還要小的那些消息已經不在 broker上了,就無法被消費

類型(父類是OffsetStore):

  • 本地文件類型
    • DefaultMQPushConsumer 的 BROADCASTING 模式,各個 Consumer 沒有互相干擾,使用 LoclaFileOffsetStore,把 Offset 存儲在本地
  • Broker 代存儲類型
    • DefaultMQPushConsumer 的 CLUSTERING 模式,由 Broker 端存儲和控制 Offset 的值,使用 RemoteBrokerOffsetStore

作用

  • 主要是記錄消息的偏移量,有多個消費者進行消費
  • 集群模式下采用 RemoteBrokerOffsetStore,broker 控制 offset 的值
  • 廣播模式下采用 LocalFileOffsetStore,消費端存儲

建議采用 pushConsumer,RocketMQ 自動維護 OffsetStore,如果用另外一種 pullConsumer 需要自己進行維護 OffsetStore

 

消息存儲 CommitLog

消息存儲是由 ConsumeQueue 和 CommitLog 配合完成

  • ConsumeQueue 是邏輯隊列,CommitLog 是真正存儲消息文件的,ConsumeQueue 存儲的是指向物理存儲的地址。Topic 下的每個 message queue 都有對應的 ConsumeQueue 文件,內容也會被持久化到磁盤。默認地址:store/consumequeue/{topicName}/{queueid}/fileName
  • CommitLog:存儲消息真正內容的文件。
    • 生成規則:
      • 每個文件的默認1G =1024 * 1024 * 1024,commitlog 的文件名 fileName,名字長度為20位,左邊補零,剩余為起始偏移量;比如 00000000000000000000 代表了第一個文件,起始偏移量為0,文件大小為1G=1 073 741 824 Byte;當這個文件滿了,第二個文件名字為00000000001073741824,起始偏移量為1073741824,消息存儲的時候會順序寫入文件,當文件滿了則寫入下一個文件。
    • 判斷消息存儲在哪個 CommitLog 上
      • 例如 1073742827 為物理偏移量,則其對應的相對偏移量為 1003 = 1073742827 - 1073741824,並且該偏移量位於第二個 CommitLog。

Broker 里面一個 Topic 里面有多個 MesssageQueue,每個 MessageQueue 對應一個 ConsumeQueue,ConsumeQueue 里面記錄的是消息在 CommitLog 里面的物理存儲地址。

 

ZeroCopy零拷貝技術

RocketMQ 高效原因

  • CommitLog 順序寫, 存儲了 MessagBody、message key、tag 等信息
  • ConsumeQueue 隨機讀 + 操作系統的PageCache + 零拷貝技術ZeroCopy
  • 零拷貝技術
    •   
      read(file, tmp_buf, len);
      write(socket, tmp_buf, len);
    • 例子:將一個 File 讀取並發送出去(Linux 有兩個上下文,內核態,用戶態)
      • File文件的經歷了4次copy
        • 調用 read,將文件拷貝到了 kernel 內核態
        • CPU 控制 kernel 態的數據 copy 到用戶態
        • 調用 write 時,user 態下的內容會 copy 到內核態的 socket 的 buffer 中
        • 最后將內核態 socket buffer 的數據 copy 到網卡設備中傳送
      • 缺點:增加了上下文切換、浪費了2次無效拷貝(即步驟2和3)
    • ZeroCopy:
      • 請求 kernel 直接把 disk 的 data 傳輸給 socket,而不是通過應用程序傳輸。ZeroCopy 大大提高了應用程序的性能,減少不必要的內核緩沖區跟用戶緩沖區間的拷貝,從而減少 CPU 的開銷和減少了 kernel 和 user 模式的上下文切換,達到性能的提升
      • 對應零拷貝技術有 mmap 及 sendfile
        • mmap:小文件傳輸快
          • RocketMQ 選擇這種方式,mmap+write 方式,小塊數據傳輸,效果會比 sendfile 更好
        • sendfile:大文件傳輸比 mmap 快
      • Java 中的 TransferTo() 實現了 ZeroCopy
      • 應用:Kafka、Netty、RocketMQ 等都采用了零拷貝技術

 

 

 


免責聲明!

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



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