RocketMQ 關鍵特性

2021-09-23 18:02:20 字數 3668 閱讀 7060

apache rocketmq之所以能在眾多的訊息中介軟體中脫穎而出,能吸引數千企業使用者與rocketmq的關鍵特性是分不開的,本文詳細介紹rocketmq中的關鍵特性。

諸如kafka之類的訊息中介軟體,在佇列數上公升時效能會產生巨大的損失,rocketmq之所以能單機支援上萬的持久化佇列與其獨特的儲存結構分不開。

如上圖所示,所有的訊息資料單獨儲存到乙個commit log,完全順序寫,隨機讀。對終端使用者展現的佇列實際只儲存訊息在commit log的位置資訊,並且序列方式刷盤。

這樣做的好處如下:

佇列輕量化,單個佇列資料量非常少。

對磁碟的訪問序列化,避免磁碟竟爭,不會因為佇列增加導致iowait增高。

每個方案都有缺點,它的缺點如下:

寫雖然完全是順序寫,但是讀卻變成了完全的隨機讀。

讀一條訊息,會先讀consume queue,再讀commit log,增加了開銷。

要保證commit log與consume queue完全的一致,增加了程式設計的複雜度。

以上缺點如何克服:

隨機讀,盡可能讓讀命中pagecache,減少io讀操作,所以記憶體越大越好。如果系統中堆積的訊息過多,讀資料要訪問磁碟會不會由於隨機讀導致系統效能急劇下降,答案是否定的。

由於consume queue儲存資料量極少,而且是順序讀,在pagecache預讀作用下,consume queue的讀效能幾乎與記憶體一致,即使堆積情況下。所以可認為consume queue完全不會阻礙讀效能。

commit log中儲存了所有的元資訊,包含訊息體,類似於mysql、oracle的redolog,所以只要有commit log在,consume queue即使資料丟失,仍然可以恢復出來。

rocketmq的所有訊息都是持久化的,先寫入系統pagecache,然後刷盤,可以保證記憶體與磁碟都有乙份資料,訪問時,直接從記憶體讀取。

在有raid卡,sas 15000轉磁碟測試順序寫檔案,速度可以達到300m每秒左右,而線上的網絡卡一般都為千兆網絡卡,寫磁碟速度明顯快於資料網路入口速度,那麼是否可以做到寫完記憶體就向使用者返回,由後台執行緒刷盤呢?

由於磁碟速度大於網絡卡速度,那麼刷盤的進度肯定可以跟上訊息的寫入速度。

萬一由於此時系統壓力過大,可能堆積訊息,除了寫入io,還有讀取io,萬一出現磁碟讀取落後情況,會不會導致系統記憶體溢位,答案是否定的,原因如下:

同步刷盤與非同步刷盤的唯一區別是非同步刷盤寫完pagecache直接返回,而同步刷盤需要等待刷盤完成才返回,同步刷盤流程如下:

寫入pagecache後,執行緒等待,通知刷盤執行緒刷盤。

刷盤執行緒刷盤後,喚醒前端等待執行緒,可能是一批執行緒。

前端等待執行緒向使用者返回成功。

豐富的訊息查詢手段,幫助使用者快速定位訊息,排查問題,rocketmq支援按message id查詢、按message key查詢等。

如上圖所示,msgid總共16位元組,包含訊息儲存主機位址,訊息commit log offset。從msgid中解析出broker的位址和commit log的偏移位址,然後按照儲存格式所在位置訊息buffer解析成乙個完整的訊息。

rocketmq可以為每條訊息指定key,並根據建立高效的訊息索引,索引邏輯結果如上圖所示,查詢過程如下:

根據查詢的key的hashcode%slotnum得到具體的槽的位置(slotnum是乙個索引檔案裡面包含的最大槽的數目,例如圖中所示slotnum=5000000)。

根據slotvalue(slot位置對應的值)查詢到索引項列表的最後一項(倒序排列,slotvalue總是指向最新的乙個索引項)。

遍歷索引項列表返回查詢時間範圍內的結果集(預設一次最大返回的32條記錄)

hash衝突;尋找key的slot位置時相當於執行了兩次雜湊函式,一次key的hash,一次key的hash值取模,因此這裡存在兩次衝突的情況;第一種,key的hash值不同但模數相同,此時查詢的時候會在比較一次key的hash值(每個索引項儲存了key的hash值),過濾掉hash值不相等的項。第二種,hash值相等但key不等,出於效能的考慮衝突的檢測放到客戶端處理(key的原始值是儲存在訊息檔案中的,避免對資料檔案的解析),客戶端比較一次訊息體的key是否相同。

儲存;為了節省空間索引項中儲存的時間是時間差值(儲存時間-開始時間,開始時間儲存在索引檔案頭中),整個索引檔案是定長的,結構也是固定的 。

rocketmq的訊息過濾方式有別於其他訊息中介軟體,是在訂閱時,再做過濾,先來看下consume queue的儲存結構。

在broker端進行message tag比對,先遍歷consume queue,如果儲存的message tag與訂閱的message tag不符合,則跳過,繼續比對下乙個,符合則傳輸給consumer。注意:message tag是字串形式,consume queue中儲存的是其對應的hashcode,比對時也是比對hashcode。

consumer收到過濾後的訊息後,同樣也要執行在broker端的操作,但是比對的是真實的message tag字串,而不是hashcode。

為什麼過濾要這樣做?

message tag儲存hashcode,是為了在consume queue定長方式儲存,節約空間。

過濾過程中不會訪問commit log資料,可以保證堆積情況下也能高效過濾。

即使存在hash衝突,也可以在consumer端進行修正,保證萬無一失。

很多業務有順序訊息的需求,rocketmq支援全域性和區域性的順序,一般推薦使用區域性順序,將具有順序要求的一類訊息hash到同乙個佇列中便可保持有序,如下圖所示。

但順序訊息,有自己的缺陷:

目前,中介軟體團隊正在攻克這些缺陷,很快將出現在新特性當中。

事務訊息特性介紹參考aliware mq的文件介紹。

日常業務中有很多定時訊息的場景,比如在電商交易中超時未支付關閉訂單的場景,在訂單建立時會傳送一條 mq 延時訊息,這條訊息將會在30分鐘以後投遞給消費者,消費者收到此訊息後需要判斷對應的訂單是否已完成支付。如支付未完成,則關閉訂單,如已完成支付則忽略。

rocketmq為了實現定時訊息,引入延時級別,犧牲部分靈活性,事實上很少有業務需要隨意指定定時時間的靈活性。定時訊息內容被儲存在資料檔案中,索引按延時級別堆積在定時訊息佇列中,具有跟普通資訊一致的堆積能力,如下圖所示。

以上為使用者比較關注的rocketmq關鍵特性,rocketmq中更多的技術將有專門的章節介紹,比如低延遲技術、高可用以及高可靠技術等。

InnoDB關鍵特性

innodb使用insert buffer 欺騙 資料庫 對於為非唯一索引,輔助索引的修改操作並非實時更新索引的葉子頁,而是把若干對同一頁面的更新快取起來做合併為一次性更新操作,轉化隨機io 為順序io,這樣可以避免隨機io帶來效能損耗,提高資料庫的寫效能。ibuf pool size per ma...

innodb 關鍵特性

插入緩衝 innodb儲存引擎對於非聚集索引的插入或更新操作,不是每一次直接插入到索引頁中,而是先判斷插入的非聚集索引頁是否在緩衝池,若在,則直接插入 不在,則先放在乙個insert buffer物件中。資料庫這個非聚集的索引已經插到葉子節點,而實際並沒有,知識存放在另乙個位置。然後再以一定的頻率和...

InnoDB的關鍵特性

1 插入緩衝 insert buffer 對於非聚集索引頁的插入或更新操作,不是每一次直接插入到索引頁中,而是先判斷插入的非聚集索引頁是否在緩衝池中,若在則直接插入 若不在則先放入到乙個insert buffer物件中。看似資料庫這個非聚集的索引已經插入到葉子節點,實際並沒有,只是存放在另乙個位置。...