一、MQ消息發送
1、發送端MQ-client(消息生產者:Producer)將消息發送給MQ-server;
2、MQ-server將消息落地;
3、MQ-server回ACK給MQ-client(Producer);
4、MQ-server將消息發送給消息接受端MQ-client(消息消費者:Customer);
5、MQ-client(Customer)消費接受到消息后發送ACK給MQ-server;
6、MQ-server將落地消息刪除
二、消息重復發送原因
為了保證消息必達,MQ使用了消息超時、重傳、確認機制。使得消息可能被重復發送,如上圖中,由於網絡不可達原因:3和5中斷,可能導致消息重發。消息生產者a收不到MQ-server的ACK,重復向MQ-server發送消息。MQ-server收不到消息消費者c的ACK,重復向消息消費者c發消息。
三、消息重復發送產生的后果
舉個例子:購買會員卡,上游支付系統負責給用戶扣款,下游系統負責給用戶發卡,通過MQ異步通知。不管是上半場的ACK丟失,導致MQ收到重復的消息,還是下半場ACK丟失,導致購卡系統收到重復的購卡通知,都可能出現,上游扣了一次錢,下游發了多張卡。
四、MQ內部如何做到冪等性的
對於每條消息,MQ內部生成一個全局唯一、與業務無關的消息ID:inner-msg-id。當MQ-server接收到消息時,先根據inner-msg-id判斷消息是否重復發送,再決定是否將消息落地到DB中。這樣,有了這個inner-msg-id作為去重的依據就能保證一條消息只能一次落地到DB。
五、消息消費者應當如何做到冪等性
1、對於非冪等性業務且要求實現冪等性業務:生成一個唯一ID標記每一條消息,將消息處理成功和去重日志通過事物的形式寫入去重表。
2、對於非冪等性業務可不實現冪等性的業務:權衡去重所花的代價決定是否需要實現冪等性,如:購物會員卡成功,向用戶發送通知短信,發送一次或者多次影響不大。不做冪等性可以省掉寫去重日志的操作。