引用: https://www.jianshu.com/p/d06e9bc6c463
RMQ採用順序寫,隨機讀
的設計理念:
- CommitLog順序寫,可以大大提高寫人效率。
- 雖然是隨機讀,但是利用操作系統的pagecache機制,可以批量地從磁
盤讀取,作爲cache存到內存中,加速後續的讀取速度。
消息存儲結構
RocketMQ消息的存儲是由ConsumeQueue
和CommitLog
配合完成的:
Commit Log
,消息真正的物理存儲文件是CommitLog
,以物理文件的方式存放,所有消息內容全部持久化到這個文件中.Consume Queue
:ConsumeQueue
是消息的邏輯隊列,類似數據庫的索引文件
,這裏存放消息在Commit Log的偏移值以及大小和Tag屬性。
如果一個Topic要發送和接收的數據量非常大,需要能支持增加並行處理的機器來提高處理速度,這時候一個Topic可以根據需求設置一個或多個MessageQueue,Topic有了多個MessageQueue後,消息可以並行地向各個
MessageQueue發送,消費者也可以並行地從多個MessageQueue讀取消息並消費。
Commit Log
: 文件地址:${user.home}/store/commitlog}${fileName}
.
Consume Queue
:文件地址在${storeRoot}\consumequeue\${topicName}\${queueld}\${fileName}
RMQ發送邏輯
寫消息
發送時,Producer不直接與Consume Queue打交道,RMQ所有的消息都會存放在Commit Log中,爲了使消息存儲不發生混亂,對Commit Log進行寫之前就會上鎖。
消息持久被鎖串行化後,對Commit Log就是順序寫,也就是常說的Append
操作。
RMQ的消息整體是有序的,所消息按順序將內容持久化在Commit Log中。
Dispatch
Commit Log持久後,會將裏面的數據Dispatch到對應的Consume Queue上。
讀消息
消費邏輯底層
消費時,Consumer不直接與Commit Log打交道,而是從Consume Queue中去拉取數據.每一個Consume Queue都是順序讀
光拉取Consume Queue是沒有數據的,裏面只有一個對Commit Log的引用,所以再次拉取Commit Log。
例子
爲了簡述方便,來個例子:假如集羣有一個Broker,Topic爲binlog的隊列(Consume Queue)數量爲4,如下圖所示,按順序發送這5條內容各不相同消息。
Message msg1 = new Message("binlog", "order", "1001", "content 111".getBytes(RemotingHelper.DEFAULT_CHARSET));
Message msg2 = new Message("binlog", "inst", "1002", "content 222".getBytes(RemotingHelper.DEFAULT_CHARSET));
Message msg3 = new Message("binlog", "menu", "1003", "content 333".getBytes(RemotingHelper.DEFAULT_CHARSET));
Message msg4 = new Message("binlog", "menu", "1004", "content 444".getBytes(RemotingHelper.DEFAULT_CHARSET));
Message msg5 = new Message("binlog", "order", "1005", "content 555".getBytes(RemotingHelper.DEFAULT_CHARSET));
寫消息
首先,RMQ的消息整體是有序的,所以這5條消息按順序將內容持久化在Commit Log中。
dispatch
Consume Queue
consume queue record format