1:什么是Offset
message queue是無限長(zhǎng)的數(shù)組秧秉,一條消息進(jìn)來下標(biāo)就會(huì)漲1,下標(biāo)就是offset芭析,
消息在某個(gè) MessageQueue里的位置板熊,通過offset的值可以定位到這條消息颜凯,或者指示Consumer從這條消息開始向后處理
message queue中的maxOffset表示消息的最大offset,
maxOffset并不是最新的那條消息的 offset悄雅,而是最新消息的offset+1, minOffset則是現(xiàn)存在的最小offset站蝠。
broker的config配置:
deleteWhen = 04 (每天凌晨4點(diǎn)刪除日志)
fileReserveTime=48 (默認(rèn)消息存儲(chǔ)48小時(shí))(48小時(shí)之前的消費(fèi)會(huì)被物理地從磁盤刪除)
message queue 的min offset也就對(duì)應(yīng)增長(zhǎng)坡脐。
所以比minOffset還要小的那些消息已經(jīng)不在broker上了卢佣,就無法被消費(fèi)。
類型(父類是0ffsetStore):
Broker代存儲(chǔ)類型:
DefaultMQPushConsumer的CLUSTERING模式栋豫,
由Broker端存儲(chǔ)和控制Offset的值挤安, 使用 RemoteBrokerOffsetStore
本地文件類型
DefaultMQPushConsumer 的 BROADCASTING 模式,
各Consumer沒有互相干擾丧鸯,使用LoclaFileOffsetStore,把Offset存儲(chǔ)在本地
offset作用:
主要是記錄消息的偏移量蛤铜,有多個(gè)消費(fèi)者進(jìn)行消費(fèi)
建議采用pushConsumer, RocketMQ自動(dòng)維護(hù)OffsetStore,
不管Offset時(shí)存儲(chǔ)在是Broker代存儲(chǔ)類型還是本地文件類型,最后都是RocketMQ進(jìn)行管理的 不需要自己管理
如果用另外一種pullConsumer丛肢,為了更加靈活的管理消息的消費(fèi)(可以針對(duì)pullConsumer對(duì)應(yīng)的方法進(jìn)行重寫)围肥,
除了Offset是存放在本地 還需要自己進(jìn)行維護(hù)OffsetStore
2:什么是CommitLog
消息存儲(chǔ)是由ConsumeQueue和CommitLog配合完成
ConsumeQueue:是邏輯隊(duì)列 (會(huì)被持久化)
CommitLog:是真正存儲(chǔ)消息文件的,存儲(chǔ)的是指向物理存儲(chǔ)的地址(會(huì)被持久化)
ConsumeQueue 存儲(chǔ)的是 消息在CommitLog中的offset蜂怎。
ConsumeQueue 可以看做是 CommitLog的索引文件穆刻。
1:可以通過ConsumeQueue保存的offset(offsetTable.offset json文件中保存的ConsumerQueue的下標(biāo))
快速的定位到CommitLog的具體消息的位置。
2:過濾tag是也是通過遍歷ConsumeQueue來實(shí)現(xiàn)的(先比較hash(tag)符合條件的再到consumer比較tag原文)
而不需要經(jīng)過CommitLog杠步。
ConsumeQueue:
Topic下的每個(gè)message queue都有對(duì)應(yīng)的ConsumeQueue文件氢伟,內(nèi)容也會(huì)被持久化到磁盤
默認(rèn)地址: store/consumequeue/{topicName}/{queueid}/fileName
CommitLog
生成規(guī)則:
每個(gè)文件的默認(rèn)1G =1024 * 1024 *1024,
commitlog的文件名fileName榜轿,名字長(zhǎng)度為20位,左邊補(bǔ)零朵锣,剩余為起始偏移量谬盐;
1:第一個(gè)文件名稱為00000000000000000000,起始偏移量為0,文件大小為1G=1 073 741 824Byte诚些;
2:當(dāng)這個(gè)文件滿了飞傀,消息存儲(chǔ)的時(shí)候會(huì)順序?qū)懭胛募?dāng)文件滿了則寫入下一個(gè)文件
3:第二個(gè)文件名字為00000000001073741824,起始偏移量為1073741824诬烹。
判斷消息存儲(chǔ)在哪個(gè)CommitLog上
例如1073742827為物理偏移量砸烦,則其對(duì)應(yīng)的相對(duì)偏移量 1073742827 - 1073741824 =為1003
并且該偏移量位于第二個(gè)CommitLog。
Broker 里面多個(gè)Topic(一對(duì)多)
一個(gè) Topic里面有多個(gè)MesssageQueue(一對(duì)多)
每個(gè) MessageQueue 都對(duì)應(yīng)一個(gè) ConsumeQueue (一對(duì)一)
ConsumeQueue里面記錄的是Off 在CommitLog里面的物理存儲(chǔ)地址
3:高性能分析之ZeroCopy零拷貝技術(shù)講解
RocketMQ的高效原因
CommitLog順序?qū)懸文鎯?chǔ)了MessagBody外冀、message key、tag等信息
ConsumeQueue隨機(jī)讀(索引)+操作系統(tǒng)的PageCache(緩存) +零拷貝技術(shù)ZeroCopy(最重要)
ConsumeQueue 與 CommitLog 的關(guān)系 :
通過 存儲(chǔ)在ConsumeQueue的offset 快速查找 CommitLog
ConsumeQueue的零拷貝技術(shù)ZeroCopy:
零拷貝技術(shù)
read(file, tmp_buf, len);
write(socket, tmp_buf, len);
例子:
將一個(gè)File讀取并發(fā)送出去(Linux有兩個(gè)上下文掀泳,內(nèi)核態(tài)雪隧,用戶態(tài))
File文件的經(jīng)歷了4次copy
kerneI = 內(nèi)核態(tài) user = 用戶態(tài)
1:調(diào)用read,將文件 從磁盤拷貝 到了內(nèi)核態(tài)
2:CPU控制 內(nèi)核態(tài)的數(shù)據(jù)拷貝 到了用戶態(tài)
3:調(diào)用write時(shí),用戶態(tài)下的內(nèi)容會(huì) 拷貝到內(nèi)核態(tài)的socket的buffer中 :
4:最后將內(nèi)核態(tài)socket buffer的數(shù)據(jù)拷貝到網(wǎng)卡設(shè)備中傳送
缺點(diǎn):增加了上下文切換员舵、浪費(fèi)了2次無效拷貝(即步驟2和3)
最關(guān)鍵是該邏輯需要經(jīng)過 用戶態(tài)(Linux系統(tǒng)的 Security Processing 處理)
不能在內(nèi)核態(tài)直接處理數(shù)據(jù)
ZeroCopy:
請(qǐng)求kernel直接把disk的data傳輸紿socket脑沿,而不是通過應(yīng)用程序傳輸。
Zero copy 大大提高了應(yīng)用程序的性能马僻,減少不必要的內(nèi)核緩沖區(qū)跟用戶緩沖區(qū)間的拷貝庄拇,
從而減少CPU的開銷和減少了 kernel和u er模式的上下文切換,達(dá)到性能的提升
對(duì)應(yīng)零拷貝技術(shù)有mmap及sendfile
-mmap:小文件傳輸快
RocketMQ選擇這種方式韭邓,mmap+write方式措近,小塊數(shù)據(jù)傳輸,效果會(huì)比sendfile更好
sendfile:大文件傳輸比mmap快
應(yīng)用:Kafka Netty RocketMq都使用了零拷貝的技術(shù)女淑。