昨天業務反饋了一個問題,一個用戶的月流水賬單重復了,拿到userid,開始定位問題之路。
查看數據庫記錄,如下圖,用戶月流水數據確實重復了(taskid同一個批次,每個月數據都有二條)。
1. 首先,看外部數據供應商是否重復推送業務數據給我,我程序中是會設置攔截重復消息
2. 查看消息接收,以及消息推送到MQ
消息接收
消息推送
看下來前面的步驟都沒有重復,再看消息的消費,如下圖所示:
原因定位:看是消費端消費了MQ中的同一條消息消費了二次,這個發生時間正好在我們上線時間,也就是上線的時候會發生消息重復消費,因為一個消息被處理之后,沒來得及提交offset消費線程就被kill掉了,然后重啟之后從MQ拿的消息還是之前的消息,當然好處是保證每條消息都保證至少會消費一次,缺點是消息可能會重復消費。
解決方案:1. 對於流程中的消息,每條消息中包含唯一id,比如業務id,在數據庫中將業務id作為Unique key,插入重復時會報duplicate key異常;
2. redis中存儲業務id,重復的時候set一下,任務丟棄,redis的key失效時間可以設置的很短,因為重復消費的一般發生間隔時間非常短。