業務背景
跟第三方系統做對接,雙方透過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會被處理,更新狀態“已處理”
至此,所有訊息都按順序被處理完了