rocketmq初識

stoneFang發表於2020-05-29

概念說明

通常一個訊息佇列需要掌握的知識點有Topic(主體)、Producer(生產者)、Consumer(消費者)、Queue(佇列)、Delivery Semantics(訊息傳遞正規化)

蛋疼的是不同的訊息佇列關於這些名詞叫法不一樣,含義也不是很精確。所以阿里起了一個專案OpenMessaging去發起首個分散式訊息領域的國際標準。不過好像並沒有多少人買賬,但這並不妨礙我們按照這個規範去梳理學習訊息佇列的知識。

有興趣的可以對照著看:https://github.com/openmessaging/specification/blob/master/specification-schema.md

rocketmq官方文件已經說的比較清楚了,不再贅述

核心流程

在這裡插入圖片描述

訊息寫入與儲存

訊息是儲存到broker中的,寫到commit log中,先寫記憶體,在刷盤。
儲存到磁碟中是直接以檔案系統的方式。為了提高磁碟寫入效率,都是順序寫,這樣所有的topic都放在了一起,這一點與kafka不同,kafka以topic作為基本單元。

單個commitlog 檔案大小為1G,之後滾動寫入不同檔案。

訊息讀取

消費者先從ConsumeQueue(訊息邏輯佇列)讀取持久化訊息的offset(偏移量)、size(大小)和訊息Tag的HashCode值,再從CommitLog中讀取訊息的真正實體內容部分;

此外為了快速定位訊息,還有一種檔案叫index,在給定訊息 Topic 和 Key 的前提下,可以快速定位訊息
在這裡插入圖片描述

注意點

使用訊息佇列時,需要注意的地方

訊息儲存時間

rocketmq預設儲存72小時,超過了,無論有沒有消費都會丟棄,通過引數fileReserverdTime來配置。
注意這個配置是全域性配置,沒法針對不同的topic設定不同的值,原因在上面已經提到過了,因為rocketmq儲存訊息是所有的topic放在一起的。

訊息有序

MessageListenerOrderly

訊息丟失

理論上可以保證不丟失(接受訊息重複,以及一定程度的寫入效能下降),

生產端
同步模式,或者非同步模式時需要處理髮送失敗情況

所以保證消費的冪等性是必須的
broker端
為了保證不丟,需要開啟同步刷盤(防止記憶體資料丟失),同步複製(防止單點故障)。
這樣是有效能損失的。刷盤機制引數flushDiskType 預設是ASYNC_FLUSH,broker 會訊息一定量後再刷盤,顯然效能更好。

消費端
消費完再CONSUME_SUCCESS
生產端,消費端都有可能因為網路問題導致訊息成功了,但是ack沒有成功,所以會重複投遞/消費。所以Delivery Semantics一般選擇At least once。應用程式必須要保證消費的冪等性

寫入效率/消費效率/消費積壓

傳送端
非同步刷盤,非同步複製情況下,兩臺4核8G,大小100Byte,寫入速度能夠達到幾萬。

通常broker端不存在瓶頸。但是由於一般業務是是共用一個叢集的,各個業務線都使用起來,流量還是很高的,需要監控報警,及時進行水平擴容。
如果能夠接受延遲,producer可以批量提交,傳送效率更高。

消費端
取決於消費邏輯是否耗時,預設單機處理執行緒consumeThreadMax (預設20)如果消費端服務時獨立的,可以調整調整更大,提高單機處理速度。

無法提高單機處理速度的時候,可以叢集水平擴充套件。不過不是無限水平擴充套件的,超過defaultTopicQueueNums 訂閱佇列數無效,該值預設值為4

應用場景

為什麼需要訊息佇列,這個問題都被講爛了,經典三大場景還是削峰填谷、非同步處理、服務解耦。
個人覺得這邊總結的比較全面。https://github.com/openmessaging/specification/blob/master/usecase.md

重點介紹下rpc場景,注意這個rpc不是rpc呼叫。是同步訊息,相當於兩次rpc。client發到server。server處理完再發到client。
在這裡插入圖片描述
這個通常用於服務間的同步處理。比如有個核心服務A,某個請求裡面需要有個高耗時的操作,為了不影響A服務,用了一個B服務來處理這個操作。這時候就會用到rpc

參考

https://tech.meituan.com/2016/07/01/mq-design.html

http://tinylcy.me/2019/the-design-of-rocketmq-message-storage-system/