一.消息投遞保證分類
消息的投遞保證主要是三種形式:
1.At most once—Messages may be lost but are never redelivered.
最多一次 --- 消息可能丟失,但絕不會重發。
2.At least once—Messages are never lost but may be redelivered.
至少一次 --- 消息絕不會丟失,但有可能重新發送。
3.Exactly once—this is what people actually want, each message is delivered once and only once.
正好一次 --- 這是人們真正想要的,每個消息傳遞一次且僅一次。
這三種消息投遞保證包含兩方面的內容:生產者發送消息和消費者消費消息。
二.生產者消息投遞保證分類
1.最多一次
客戶端只發送一次,不關心發送成功與否
2.至少一次
通常會設置一個最大重試次數,在發送失敗且未達到重試次數前,會多次重試。
當消息中間件保存消息成功但向客戶端響應失敗的情況下,生產者會將同一條消息發送多次,導致消息重復。
3.正好一次
1)需要生產者能夠根據消息中的內容生產一個唯一且不重復的ID,如果ID相同則認為消息體相同
2)如果消息中間件支持根據某一個屬性進行冪等操作,則直接利用該特性實現“正好一次”。即使消息中間件具備該功能,也是有時間限制的,在使用時需要具體了解
3)如果消息中間件不支持該特性,則無法實現該中投遞保證。因為對於消息中間件保存消息成功但向客戶端響應失敗的情況在生產者一端是沒有辦法解決的
三.消費者消息投遞保證分類
1.最多一次
先更新消費的offset,而后進行消息消費,這樣消息處理過程中崩潰了(進程或者機器),也不會再次進行消費。
2.至少一次
先處理消息,處理完成后再更新消費的offset。這樣當消息處理過程中崩潰了(進程或者機器),當恢復后會再次消費消息。
3.正好一次
通常需要在消費者位置的存儲和消費者輸出的存儲之間引入分布式事務來實現,只有當消息處理成功后再更新消息的offset,通過這種方式來保證“正好一次”。 一個簡單的方法是把記錄消息消費的offset和消息處理結果使用同一條sql保存在一張表中。
也可以采用“二級消費"的方式來實現”正好一次“,自己搭建一個系統和db來存儲消息ID,對重復的消息ID進行過濾,來保證重復的消息只有一條(http://blog.jobbole.com/111809/?utmsource=blog.jobbole.com&utmmedium=relatedPosts)。
四.通常選擇
對於大多數系統而言,是不會接受消息丟失,而正好一次的實現成本又比較高,因而在消息中間件實際的運用中,使用最廣泛的是“至少一次”這種投遞保證,也是消息中間件的默認選項。
五.參考資料
1.http://orchome.com/21