rocketmq初識

  • 2020 年 5 月 29 日
  • 筆記

概念說明

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

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

有興趣的可以對照着看://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

應用場景

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

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

參考

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

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