消息隊列是如何保證高可用的?redis
已RocketMQ爲例:數據庫
NameServer相似於kafka的zk,起到master和slave的註冊和發現。 Producer和NameServer集羣的隨機一點創建長連接,按期從NameServer獲取Topic路由信息,並向Topic服務的Broker Master創建長連接,且定時向Broker發送心跳。網絡
Producer發送消息到Broker master,Consumer能夠從Topic的Master和Slave的broker訂閱消息。架構
對比看下kafka的架構圖: 異步
經過zk管理集羣配置,選舉leader及對consumer group進行rebalance。 consumer能夠採用pull和push方式訂閱消息。blog
RabbitMq能夠經過普通集羣和鏡像模式進行可用性保證。隊列
不一樣的MQ有不一樣的消費機制,ack以後消息會從消息隊列中刪除。 形成重複消費的緣由可能有如下幾點:事務
業務上的解決:路由
可靠性從如下幾個調度考慮:kafka
RabbitMq的transaction機制,在發送消息以前,開啓事務,而後發送消息,若是出現異常進行回滾,發送成功執行commit。
信道發出去的消息會被指派一個惟一ID,消息路由到隊列後,隊列會返回Ack信息其中包含惟一ID,打到確認目的,若是沒能處理此消息,會返回NAck,以後進行重試操做。
隊列爲防止丟數據,通常開啓磁盤持久化,能夠在confirm持久化磁盤後返回ack,這樣保證了消息的持久化。
消費者能夠採用自動確認模式,確認後當即刪除,爲解決丟失數據後,重複消費,能夠關閉自動確認,採用手動確認。
producer發送消息到partition後,經過zk找到partition的leader,leader寫入本地log,follower主動從leader來pull數據。
能夠配置produder的acks=all,這樣須要follower同步後才確認消息發送成功。 producer設置retries=MAX,寫入失敗後會進入無限重試。
爲保證zk切換leader過程當中數據丟失,能夠配置replication.factor,即設置副本數量,要求每一個partition必須至少2個副本。min.insync.replicas,是leader須要感知至少多少個follower和本身保持聯繫。
kafka消費主要依賴於offset,每一個消費組消費的消息都有惟一的offset下標,消費者消費後提交offset。
業務上通常沒有這類需求,通常能夠採用將消息放到一個信道里面,kafka的partiton,rabbitMq的queue,而後控制消費者順序消費。