1. 程式人生 > >解決rabbitmq訊息佇列的順序及重複消費問題

解決rabbitmq訊息佇列的順序及重複消費問題

五一期間去韓國遊玩,順便去了朋友公司扯淡去了。 所謂的扯淡,就是過去聽技術分享,有python, golang, devops,docker一些話題。總的來說,技術方面跟國內還是有一些差距的。 

正題開始,因為業務的各方面的強需求,我們使用了rabbitmq作為訊息佇列,利用rabbitmq的ack機制來確認訊息的可靠性。 但是rabbitmq本身是沒有絕對的訊息順序機制的,單個queue在多消費者下不能保證其先後順序。  另外ack的機制會觸發訊息重複消費的,需要我們在設計上避免該問題。

關於訊息的重複執行

首先我們可以確認的是,觸發訊息重複執行的條件會是很苛刻的! 也就說 在大多數場景下不會觸發該條件!!! 一般出在任務超時,或者沒有及時返回狀態,引起任務重新入佇列,重新消費!  在rabbtimq裡連線的斷開也會觸發訊息重新入佇列。  

消費任務型別最好要支援冪等性,這樣的好處是 任務執行多少次都沒關係,頂多消耗一些效能! 如果不支援冪等,比如傳送資訊? 那麼需要構建一個map來記錄任務的執行情況! 不僅僅是成功和失敗,還要有心跳!!!  這個map在消費端實現就可以了!!!    這裡會出現一個問題,有兩個消費者 c1, c2 ,一個任務有可能被c1消費,如果再來一次,被c2執行? 那麼如何得知任務的情況? 任務派發!  任務做成hash,固定消費者! 堅決不要想方設法在mq擴充套件這個future。

一句話,要不保證訊息冪等性,要不就用map記錄任務狀態.

關於訊息的絕對順序執行

我們遇到的大多數場景都不需要訊息的有序的,如果對於訊息順序敏感,那麼我們這裡給出的方法是 訊息體通過hash分派到佇列裡,每個佇列對應一個消費者,多分拆佇列。 為什麼要這麼設計?  同一組的任務會被分配到同一個佇列裡,每個佇列只能有一個worker來消費,這樣避免了同一個佇列多個消費者消費時,亂序的可能! t1, t2 兩個任務, t1 雖然被c1先pop了,但是有可能c2先把 t2 任務給完成了。

一句話,主動去分配佇列,單個消費者。

基於Rabbitmq的多工處理框架

這裡提一下,我們用rabbitmq實現了一個頗為複雜的架構,節省了太多的mq連線及消耗。通過python pika gevent實現的,因py有gil,所以使用多程序來跑多核,程序之間不使用共享變數,而是用佇列來傳遞ack訊號。  

這裡實現的場景是用pika消費rabbitmq,然後把獲取到的任務提丟到佇列,另一個程序去消費該任務,然後觸發ack。 

END.

http://xiaorui.cc/2017/05/04/%E8%A7%A3%E5%86%B3rabbitmq%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97%E7%9A%84%E9%A1%BA%E5%BA%8F%E5%8F%8A%E9%87%8D%E5%A4%8D%E6%B6%88%E8%B4%B9%E9%97%AE%E9%A2%98/