業務背景 跟第三方系統做對接,雙方通過ActiveMQ進行通信,消息之間是有內在關聯的,也就是消息本來應該是有業務順序的,但由於一些原因,現在收到消息是亂序的,這種情況下做業務處理就有一點小問題了 方案一:自己重排序 收到消息後,自己在記憶體排序,然後按順序丟到隊列中,自己控制消息的發送和接收保證收到 ...
業務背景
跟第三方系統做對接,雙方通過ActiveMQ進行通信,消息之間是有內在關聯的,也就是消息本來應該是有業務順序的,但由於一些原因,現在收到消息是亂序的,這種情況下做業務處理就有一點小問題了
方案一:自己重排序
收到消息後,自己在記憶體排序,然後按順序丟到隊列中,自己控制消息的發送和接收保證收到按發送的順序來收到消息。
如果自己排序的話就要對每個消息標記一個順序,同時還要指定預先定義好哪些消息屬於一類並且相互之間有依賴順序。
具體實現的話,可以這樣做:
1、收到一條消息,封裝一下加個序號,放到Redis中,用列表或者有序集合來存儲,同時用字元串類型存一下這個業務單號的當前最小序號(預設是1)
2、如果是用有序集合存的話,用序號當做分數,這樣消息丟進去就已經排好序了,每次用最小分數的那個元素和當前最小序號比較,如果小於或等於,則刪除這個元素,將它發送到MQ,同時最小序號加1
3、如果用列表存的話,可以lpush添加,lrange查最先放進去的那個元素,和當前最小序號比較,小於或等於,則rpop刪除,發MQ,最小序號加1
大概就是這麼個意思,以上是我的思路,沒有實現,感覺應該是可行的
方案二:定時任務掃描
1、收到消息後,先存到資料庫中,這條記錄的狀態為“未消費”
2、進行業務處理
(1)如果處理這條消息不需要依賴其它的消息,或者它依賴的消息已經先於它被處理了,那麼直接做業務處理,完成後更新消息記錄表,將這條記錄的狀態置為“已處理”
(2)如果這條消息依賴的消息還沒有收到(通常表現為可能是某個表的數據狀態不對或者沒有數據,等等),則不處理
3、定時任務掃描消息記錄表,找到那些狀態為“未處理”的數據,調用統一的消息處理介面,依次執行,邏輯同上
舉個例子,
假設某個業務場景會收到5個消息,順序假設為1、2、3、4、5
最極端的情況,假設先收到5,存表,暫不處理
再收到4,存表,暫不處理
3,存表,暫不處理
2,存表,暫不處理
1,存表,立即處理,更新狀態“已處理”
定時任務第一次掃描,2會被處理,更新狀態“已處理”
第二次掃描,3會被處理,更新狀態“已處理”
第三次掃描,4會被處理,更新狀態“已處理”
第四次掃描,5會被處理,更新狀態“已處理”
至此,所有消息都按順序被處理完了