分散式部署服務的情況下,由於網路狀況不可預期,消息有可能發送成功,但是消費端消費失敗;也有可能消息根本沒有發出去,如何保證消息是否發送成功是經常遇到的問題。最近有時間研究了一下,具體方法如下圖: 表結構設計如下: 具體思路: 正常流程(網路都正常) 1.消息生產方,將消息信息與業務數據在同一個事務中 ...
分散式部署服務的情況下,由於網路狀況不可預期,消息有可能發送成功,但是消費端消費失敗;也有可能消息根本沒有發出去,如何保證消息是否發送成功是經常遇到的問題。最近有時間研究了一下,具體方法如下圖:
表結構設計如下:
具體思路:
正常流程(網路都正常)
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分散式鎖。
demo地址為https://github.com/cysnet/mq-trans.git