分布式部署服務的情況下,由於網絡狀況不可預期,消息有可能發送成功,但是消費端消費失敗;也有可能消息根本沒有發出去,如何保證消息是否發送成功是經常遇到的問題。最近有時間研究了一下,具體方法如下圖:
表結構設計如下:
具體思路:
正常流程(網絡都正常)
1.消息生產方,將消息信息與業務數據在同一個事務中存入數據庫。
2.消息發送發,發送消息,消息發送表‘狀態’為‘已發送’
3.消息消費方,接收消息,存入消息接收表,並調用生產方接口,更新生產方消息發送表‘狀態’為‘已完成’。
正常流程結束。
異常流程
1.消息生產方,將消息信息與業務數據在同一個事務中存入數據庫。
2.消息發送發,發送消息,消息發送表‘狀態’為‘已發送’
3.消息消費方未收到消息;或,接收到消息,存入消息接收表,但調用生產方接口失敗。
4.消息生產方job1,查詢消息發送表‘狀態’為‘已發送’,並當前時間超過回調截止時間(或過期時間)的記錄,然后調用消息消費方查詢狀態接口
5.消息生產方job1若查到結果,則更新消息發送表‘狀態’為‘已完成’,流程結束;若為查到結果,則更新消息發送表‘狀態’為‘未發送’
6.消息生產方job2,查詢消息發送表‘狀態’為‘未發送’的記錄,重新生產消息,並更新狀態為“已發送”。之后會自動跳轉到流程3,直到狀態變更為“已完成”。
注意,消息接收表的sourcemsg_id字段需唯一,保證冪等性。
針對這個設計,完成了net core3.1 的demo,用了rabbitmq作為消息隊列,mysql作為數據庫,ef core orm,redis分布式鎖。