天天看點

阿裡百度華為消息隊列MQ異步場景面試題(上)

1 在使用者注冊後發送消息到MQ,然後會員服務監聽消息進行異步處理的場景下,有些時候我們會發現,雖然使用者服務先儲存資料再發送MQ,但會員服務收到消息後去查詢資料庫,卻發現資料庫中還沒有新使用者的資訊。你覺得,這可能是什麼問題呢,又該如何解決呢?

解決方案

當時倒不是因為主從的問題,而是因為業務代碼把儲存資料和發MQ消息放在了一個事務中,有機率收到消息的時候事務還沒有送出完成,當時開發同學的處理方式是收MQ消息的時候sleep 1秒,或許應該是先送出事務,完成後再發MQ消息,但是這又出來一個問題MQ消息發送失敗怎麼辦?是以後來演化為建立本地消息表來確定MQ消息可補償,把業務處理和儲存MQ消息到本地消息表操作在相同僚務内處理,然後異步發送和補償發送消息表中的消息到MQ

可能是資料寫到了主庫,然後查詢了從庫。但因為主從同步有延遲,導緻沒有查詢到

也可能mq發資訊寫到了事務中,導緻了mq的消費時,事務還沒有送出

注冊register的代碼中把異常都吃掉了,沒抛出來,注冊又報錯了,但還是繼續執行并且發了消息

先儲存使用者注冊的資料,同時記錄下要發送mq的消息,入庫在一個事務

通過異步任務定時拉取mq的消息表,發送到mq,進行處理

(其實這就是本地事務消息的實作)第二步不一定需要定時任務拉取。第一步完成後直接發mq即可 定時任務拉取隻用來補償

生産者發送給mq消息 即使異步發送也會有listener 來監聽投遞消息是否成功 如果失敗 重試不就行了 ? 不是類似kafka 有100%投遞 100%保證消費的配置嗎?

補償嗎?我遇到過mq癱瘓的情況,沒有補償這個時候除了幹着急我們還能做啥

如果有多個補償執行個體,會不會造成消息重複?

補償需要配合幂等,生産應用肯定用資料庫做幂等。

2 除了使用Spring AMQP實作死信消息的重投遞外,RabbitMQ 2.8.0 後支援的死信交換器DLX也可以實作類似功能。你能嘗試用DLX實作嗎,并比較下這兩種處理機制?

自定義的私信隊列,其實是發送失敗,主要是生産者發送到mq的時候,發送失敗,進了自定義的私信隊列;

DLX的方式的方式其實解決已到了mq,但是因為各種原因,無法到達正常的隊列中,大概分類下面幾種吧:

消息消費時被拒絕(basic.reject / basic.nack),并且requeue = false

消息TTL過期

隊列達到最大長度

公司内部分享的RabbitMQ的資料,歡迎大家交流

http://note.youdao.com/noteshare?id=e9f2f88c6c7fcb7ac690463eb230650a