RocketMQ訊息亂序場景及解決方法

2021-10-02 15:50:39 字數 1441 閱讀 5241

訊息亂序也是rocketmq中的乙個常見問題,那麼到底為什麼會出現訊息亂序呢?

首先我們知道在rocketmq的topic中,會有多個messagequeue作為資料分片,每個messagequeue都會儲存部分的訊息,那麼在生產者產生訊息傳送到topic上的時候,按道理這些訊息都會均勻的分布在多個messagequeue中,假如我現在有多個訊息,它們是按照順序排列的,現在它們分布到了不同的messagequeue中,消費者組中的多個消費者需要去消費這些資料,每個messagequeue只能被乙個消費者消費,所以這一批有序的訊息被多個不同的消費者消費到了,誰先被消費就無法得到保障了。

如上圖所示,多個訊息分布在多個messagequeue中,最後被多個不同的消費者消費,就可能會出現訊息亂序的場景。

既然知道了訊息亂序的產生原因,那麼解決起來就簡單了,只要將有序的訊息按照順序都放入同乙個messagequeue中,最後就能被同乙個消費者順序消費了。

要將訊息都傳送到同乙個messagequeue中,最簡單的方式就是使用取模了,可以根據訊息的唯一標識,比如是乙個orderid,根據orderid取模然後將一批有序訊息放入同乙個messagequeue中,核心**如下:

sendresult sendresult = producer.

send

(msg,

newmessagequeueselector()

}, orderid)

;

完整**可以去rocketmq原始碼中的example包下的ordermessage中檢視。

那如果消費者在消費順序訊息的時候,消費失敗了,之後的訊息該怎麼辦呢?

常見的訊息消費失敗之後,我們一般會返回consumeconcurrentlystatus.recosume_later這個狀態,這個狀態會告訴rocketmq將這條訊息放入到重試佇列中稍後重試,但是這樣就會導致之後的訊息先被消費了。

所以這裡我們需要返回consumeorderlystatus.suspend_current_queue_a_moment,這個狀態是讓當前的佇列等一會再繼續消費,只有在前面的訊息被消費了才能輪到後面的訊息,後面的訊息都得等著。

所以在消費者的**中,我們需要使用如下的方法:

@override

public consumeorderlystatus consumemessage

(list

msgs, consumeorderlycontext context)

else

}

按照上面的方案就可以保證訊息的順序消費了。

RocketMQ訊息型別

普通資訊也叫做無序訊息,簡單來說就是沒有順序的訊息,producer 只管傳送訊息,consumer 只管接收訊息,至於訊息和訊息之間的順序並沒 可能先傳送的訊息先消費,也可能先傳送的訊息後消費。舉個簡單例子,producer 依次傳送 order id 為 1 2 3 的訊息到 broker,co...

RocketMQ 事務訊息

一 事務訊息實現方式 應用使用事務訊息的步驟 1 應用傳送訊息,使用prepare欄位標示準備訊息 2 應用執行本地業務邏輯 3 應用傳送事務提交或回滾訊息 broker收到prepare訊息後會將topic替換為rmq sys trans half topic,queueid替換為0,然後寫入co...

rocketMq訊息查詢

最近有人問我知道rocketmq是怎麼查詢訊息的,我發現我貌似回答不上來,所以抽空就把這塊內容補充一下,主要是講清楚根據key查詢訊息和根據msgid查詢訊息兩塊內容。看下引數列表中我們可以看到 k指出了核心key的引數,指定了根據key查詢訊息的方法,這個命令返回的是msgid,據說還有一些坑,可...