摘要:順序訊息是指對于一個指定的 Topic ,訊息嚴格按照先進先出(FIFO)的原則進行訊息發布和消費,即先發布的訊息先消費,后發布的訊息后消費,
本文分享自華為云社區《RocketMQ 順序消費機制》,作者: 勇哥java實戰分享 ,
順序訊息是指對于一個指定的 Topic ,訊息嚴格按照先進先出(FIFO)的原則進行訊息發布和消費,即先發布的訊息先消費,后發布的訊息后消費,
順序訊息分為磁區順序訊息和全域順序訊息,
1、磁區順序訊息
對于指定的一個 Topic ,所有訊息根據 Sharding Key 進行區塊磁區,同一個磁區內的訊息按照嚴格的先進先出(FIFO)原則進行發布和消費,同一磁區內的訊息保證順序,不同磁區之間的訊息順序不做要求,
- 適用場景:適用于性能要求高,以 Sharding Key 作為磁區欄位,在同一個區塊中嚴格地按照先進先出(FIFO)原則進行訊息發布和消費的場景,
- 示例:電商的訂單創建,以訂單 ID 作為 Sharding Key ,那么同一個訂單相關的創建訂單訊息、訂單支付訊息、訂單退款訊息、訂單物流訊息都會按照發布的先后順序來消費,
2、全域順序訊息
對于指定的一個 Topic ,所有訊息按照嚴格的先入先出(FIFO)的順序來發布和消費,
- 適用場景:適用于性能要求不高,所有的訊息嚴格按照 FIFO 原則來發布和消費的場景,
- 示例:在證券處理中,以人民幣兌換美元為 Topic,在價格相同的情況下,先出價者優先處理,則可以按照 FIFO 的方式發布和消費全域順序訊息,
全域順序訊息實際上是一種特殊的磁區順序訊息,即 Topic 中只有一個磁區,因此全域順序和磁區順序的實作原理相同,
因為磁區順序訊息有多個磁區,所以磁區順序訊息比全域順序訊息的并發度和性能更高,
訊息的順序需要由兩個階段保證:
- 訊息發送
如上圖所示,A1、B1、A2、A3、B2、B3 是訂單 A 和訂單 B 的訊息產生的順序,業務上要求同一訂單的訊息保持順序,例如訂單 A 的訊息發送和消費都按照 A1、A2、A3 的順序,
如果是普通訊息,訂單A 的訊息可能會被輪詢發送到不同的佇列中,不同佇列的訊息將無法保持順序,而順序訊息發送時 RocketMQ 支持將 Sharding Key 相同(例如同一訂單號)的訊息序路由到一個佇列中,
- 訊息消費
消費者消費訊息時,需要保證訊息消費順序和存盤順序一致,最終實作消費順序和發布順序的一致,
我們知道負載均衡服務是客戶端開始消費的起點,在負載均衡階段,并發消費和順序消費并沒有什么大的差別,最大的差別在于:向 Borker 申請鎖 ,
消費者根據分配的佇列 messageQueue ,向 Borker 申請鎖 ,如果申請成功,則會拉取訊息,如果失敗,則定時任務每隔20秒會重新嘗試,
見上圖,順序消費核心流程如下:
1、 組裝成消費物件
2、 將請求物件提交到消費執行緒池
和并發消費不同的是,這里的消費請求包含消費快照 processQueue ,訊息佇列 messageQueue 兩個物件,并不對訊息串列做任何處理,
3、 消費執行緒內,對消費佇列加鎖
4、 從消費快照中取得待消費的訊息串列
消費快照 processQueue 物件里,創建了一個紅黑樹物件 consumingMsgOrderlyTreeMap 用于臨時存盤的待消費的訊息,
5、 執行訊息監聽器
執行監聽器邏輯容易理解,消費快照的消費鎖 consumeLock的作用是:防止 Rebalance 執行緒把當前消費的 MessageQueue 物件移除掉,
6、 處理消費結果
消費成功時,首先計算需要提交的偏移量,然后更新本地消費進度,
消費失敗時,分兩種場景:
- 假如已消費次數小于最大重試次數,則將放入物件 consumingMsgOrderlyTreeMap 用例臨時存盤的待消費的訊息,重新加入到消費快照紅黑樹msgTreeMap中,然后使用定時任務嘗試重新消費,
- 假如已消費次數大于等于最大重試次數,則將失敗訊息發送到 Broker ,Broker 接收到訊息后,會加入到死信佇列里 , 最后計算需要提交的偏移量,然后更新本地消費進度,
我們做一個關于順序消費的總結:
- 順序消費需要由兩個階段訊息發送和訊息消費協同配合,底層支撐依靠的是 RocketMQ 的存盤模型;
- 順序消費服務啟動后,通過三把鎖的機制,訊息佇列 messageQueue 的資料都會被消費者實體單執行緒的執行消費;
- 假如消費者擴容,消費者重啟,或者 Broker 宕機 ,順序消費也會有一定幾率較短時間內亂序,所以消費者的業務邏輯還是要保障冪等,
點擊關注,第一時間了解華為云新鮮技術~
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/553841.html
標籤:其他
下一篇:返回列表
