java面試一日一題:rabbitMQ如何保證消息不丟失

問題:請講下rabbitMQ如何保證消息不丟失數據庫

分析:該問題屬於概念題,同時也是一個設計方面的題,牽扯到部分設計層面的東西;異步

回答要點:設計

主要從如下幾點去考慮,日誌

一、rabbitMQ在保證消息不丟失方面是怎麼作的?blog

二、在硬盤壞掉的狀況下如何保證消息不丟失?接口

 

如上圖,在使用中大致都是這樣的形式,要保證消息的不丟失,須要從上圖中三個方面去考慮it

生成者集羣

保證生成者發送的消息成功到達rabbitMQ,在這裏可使用rabbitMQ的API中提供的cofirm/callback和confirm/rollback機制,即在rabbitMQ成功接收到消息後回回調該方法,只要成功了那麼生成方就能夠認爲消息發送成功;定時任務

rabbitMQ高可用

要保證rabbitMQ不丟失消息,那麼就須要開啓rabbitMQ的持久化機制,即把消息持久化到硬盤上,這樣即便rabbitMQ掛掉在重啓後仍然能夠從硬盤讀取消息;第二點,延申下若是rabbitMQ單點故障怎麼辦,這種狀況倒不會形成消息丟失,這裏就要提到rabbitMQ的3種安裝模式,單機模式、普通集羣模式、鏡像集羣模式,這裏要保證rabbitMQ的高可用就要配合HAPROXY作鏡像集羣模式;第三點若是硬盤壞掉怎麼保證消息不丟失,這個放到下面講;

消費者

消費者要保證消息不丟失,就是rabbitMQ要知道消費者是否成功消費消息了,只有在成功消費後rabbitMQ纔會刪除該消息,這裏要開啓rabbit的手動確認機制,即只有在消費者消費完成後給rabbitMQ一個確認,這樣才證實該消息是成功消費的;

在系統中引入了rabbitMQ的目的是爲了異步、削峯、解耦,但從上面能夠看到引入rabbitMQ後系統複雜度反而升高了。

 

下面說若是rabbitMQ所在的硬盤壞了怎麼保證消息不丟失

如上圖,

一、生產者向mq發送消息的同時,再異步的把消息寫入本地的數據庫中,在數據庫中記錄每條消息的消息及狀態;

二、消費者成功消費後更新「消息日誌表」中相應消息的狀態;

三、另起一個定時任務去掃描「日誌消息表」,把那些未成功消費的消息,再向rabbitMQ重發;

四、因爲作了重發操做,因此要作好消費者接口的冪等設計;

不過這會帶來另外的問題,在生產者大量產生消息的時刻,寫DB會是一個瓶頸,同時怎麼保證寫入db的消息和發送給MQ的消息是一致的。歡迎你們踊躍留言,感謝@