RocketMQ訊息順序傳送和消費問題

2021-10-02 06:18:12 字數 1249 閱讀 3646

事故現場分析:

由於創新業務產品上線,運營產品想通過一些活動來刺激使用者,採用註冊邀請機制即可獲取積分的相關活動。考慮到後續可能還有其他可能的活動來發放積分,所以設計的時候,採用mq訊息模式發放積分,非同步解耦,並能夠保證資料的最終一致性。考慮到使用者積分計算的時候可能存在併發操作的情況,想到兩種解決方案:

1.採用分布式鎖的方式,計算使用者積分,同乙個使用者操作時保持同步處理

2.採用佇列的先天優勢,fifo的特性,只要保證同乙個使用者的積分放在同乙個佇列下,佇列能夠順序消費即可保證使用者積分計算同步進行。

經過思考和篩選最終決定採用rocketmq佇列fifo計算積分,所以不知不覺已經深陷泥潭。由於公司公司封裝的mq訊息處理並沒有做訊息的順序傳送和訊息的相關封裝,於是自己在公司公共的方法上重新封裝了一層順序傳送訊息的方法,採用使用者唯一id的hash求餘選擇傳送佇列,保證了同個使用者的積分訊息能夠傳送到同乙個佇列之中,然後想當然的認為mq在消費訊息的時候,是取一條消費一條success後再去消費其他的佇列訊息。於是開發完成就提測了,結果測試在做併發測試的時候使用者積分計算總是比實際發放的積分數要少。於是,開始陷入沉思······

事故排查:

於是開始懷疑自己的**問題,查呀查呀······邏輯一點問題沒有。於是開始了猜想:

1.難道是訊息傳送丟失?或者傳送的時候不在同乙個佇列?

於是暴力列印訊息傳送日誌,經過檢視日誌,發現訊息傳送和消費一切正常。並且根據hash演算法同乙個人也在同乙個佇列裡面,但是為什麼還是出現併發計算了呢?

2.訊息消費的時候是併發消費的?

由於之前對rocketmq的熟練度不夠,不清楚原來順序消費也要用方法保證的採用messagelistenerorderly這個listen消費的才能能保證訊息的順序消費,於是翻看公司封裝的訊息方法採用的是defaultmessagelistener。broker並不能完全保證訊息的順序消費,它僅僅能保證的訊息的順序傳送而已!,只要順序的傳送,再保證乙個執行緒只去消費乙個佇列上的訊息,那麼他就是有序的。

解決方案:

對公司的mq方法封裝,做了二次封裝採用使用者唯一id的hashcode求餘選擇佇列並採用messagelistenerorderly監聽和消費訊息,保證訊息消費的順序性。測試併發計算解決,積分計算問題完全正確。

RocketMQ 訊息傳送

訊息傳送基本流程 1 訊息驗證 驗證主題 topic 訊息體不能為空和大小不能超過4m。2 路由查詢 a 檢視快取,是否有topic的路由資訊。b 如果沒有則到nameserver中獲取路由資訊,如果快取內能找到則獲取相應路由資訊。c 從快取中獲取上一次異常的broker節點資訊,跟獲取到的節點資訊...

順序訊息 RocketMQ

訊息有序指的是可以按照訊息的傳送順序來消費。rocketmq可以嚴格的保證訊息有序。但這個順序,不是全域性順序,只是分割槽 queue 順序。要全域性順序只能乙個分割槽。之所以出現你這個場景看起來不是順序的,是因為傳送訊息的時候,訊息傳送預設是會採用輪詢的方式傳送到不通的queue 分割槽 如圖 而...

RocketMq傳送訊息Producer配置

在使用阿里的rocketmq傳送資料時,大資料量,多執行緒情況下,會產生並非網路原因的傳送失敗.故使用以下傳送方式,方法是採用內部靜態型別的單例模式.component public class producerbeansingleton private string producerid valu...