RocketMQ消息順序發送和消費問題

事故現場分析:

由於創新業務產品上線,運營產品想通過一些活動來刺激用戶,採用註冊邀請機制即可獲取積分的相關活動。考慮到後續可能還有其他可能的活動來發放積分,所以設計的時候,採用mq消息模式發放積分,異步解耦,並能夠保證數據的最終一致性。考慮到用戶積分計算的時候可能存在併發操作的情況,想到兩種解決方案:
1.採用分佈式鎖的方式,計算用戶積分,同一個用戶操作時保持同步處理
2.採用隊列的先天優勢,FIFO的特性,只要保證同一個用戶的積分放在同一個隊列下,隊列能夠順序消費即可保證用戶積分計算同步進行。
經過思考和篩選最終決定採用RocketMQ隊列FIFO計算積分,所以不知不覺已經深陷泥潭。由於公司公司封裝的MQ消息處理並沒有做消息的順序發送和消息的相關封裝,於是自己在公司公共的方法上重新封裝了一層順序發送消息的方法,採用用戶唯一Id的hash求餘選擇發送隊列,保證了同個用戶的積分消息能夠發送到同一個隊列之中,然後想當然的認爲MQ在消費消息的時候,是取一條消費一條SUCCESS後再去消費其他的隊列消息。於是開發完成就提測了,結果測試在做併發測試的時候用戶積分計算總是比實際發放的積分數要少。於是,開始陷入沉思······

事故排查:

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

1.難道是消息發送丟失?或者發送的時候不在同一個隊列?
於是暴力打印消息發送日誌,經過查看日誌,發現消息發送和消費一切正常。並且根據Hash算法同一個人也在同一個隊列裏面,但是爲什麼還是出現併發計算了呢?
2.消息消費的時候是併發消費的?
由於之前對RocketMq的熟練度不夠,不清楚原來順序消費也要用方法保證的採用MessageListenerOrderly這個listen消費的才能能保證消息的順序消費,於是翻看公司封裝的消息方法採用的是DefaultMessageListener。broker並不能完全保證消息的順序消費,它僅僅能保證的消息的順序發送而已!,只要順序的發送,再保證一個線程只去消費一個隊列上的消息,那麼他就是有序的。

解決方案:

對公司的MQ方法封裝,做了二次封裝採用用戶唯一ID的Hashcode求餘選擇隊列並採用MessageListenerOrderly監聽和消費消息,保證消息消費的順序性。測試併發計算解決,積分計算問題完全正確。

在這裏插入圖片描述

發佈了27 篇原創文章 · 獲贊 1 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章