面試題
如何保證消息沒有重復消費?或者說,如何保證消息消費的冪等性?
考察緣由
消息消費,肯定就要考慮到消息是否被重復消費?能不能避免重復消費?或者重復消費了也別造成系統異常可以嗎?這個是 MQ 領域的基本問題,其實本質上還是問你使用消息隊列如何保證冪等性,這個是你架構里要考慮的一個問題。
面試題剖析
一、重復消費產生的問題描述
因為消息發送是基于網絡發送的,假設網絡延遲或者網絡卡頓,消息發送機制多次重試,消息重復發送的問題不可避免的發生。要直接避免不重復發送基本太難,因為網絡環境無法預知,還會使程序復雜度加大,因此默認允許消息重復發送。因此無論是點對點,還是發布/訂閱模型,都可能出現生產者發送多條一樣的數據到MQ,此時就會出現重復數據。
二、如何保證消息不被重復消費
基于以上問題描述, MQ 自己保證發送的消息不重復,這就需要我們開發來保證的。
2.1、ActiveMQ
消費者接收到消息時,將消息對象進行MD5加密,作為消息唯一性。如果發現messageObj(發送到mq的數據)已經存在,則忽略,進而保證消息不被重復消費。
String md5 = MD5.encrypt(t.getMessageObj());
List list =super.query("SELECT * FROM message_mq WHERE MD5=? AND STATUS>=? AND STATUS<=? ",this, md5, MessageMq.MessageStatus.MESSAGE_STATUS_NORMAL, MessageMq.MessageStatus.MESSAGE_STATUS_HANDLE);
if (list !=null && list.size() >0) {
log.info("已經有相同消息存在,忽略此消息!!! 【MESSAGE_ID】=" + t.getMessageId() +",【MESSAGE_TYPE】=" + t.getMessageType());
return 0;// 已經有相同的消息
}
冪等性:聯想到之前數學學習的冪等性,即使公式:f(x)=f(f(x)) 能夠成立的數學性質。用在編程領域,則意為對同一個系統,使用同樣的條件,一次請求和重復的多次請求對系統資源的影響是一致的。而計算機冪等性,直白講就是,就一個數據,或者一個請求,給你重復來多次,你得確保對應的數據是不會改變的,不能出錯。