消息隊列是如何保證高可用的

消息隊列是如何保證高可用的?redis

可靠性保證

已RocketMQ爲例:數據庫

  • 集羣爲多master模式
  • 多master多slave異步複製模式
  • 多master多slave同步複製模式

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以後消息會從消息隊列中刪除。 形成重複消費的緣由可能有如下幾點:事務

  • 網絡傳輸故障
  • 消息確認沒有返回隊列服務端

業務上的解決:路由

  • 若是數據庫消費,能夠創建惟一約束,避免髒數據
  • 引入redis作冪等查詢

消息的可靠性傳輸

可靠性從如下幾個調度考慮:kafka

  • 生產者丟數據
  • 消息隊列丟數據
  • 消費者丟數據

RabbitMq的transaction機制,在發送消息以前,開啓事務,而後發送消息,若是出現異常進行回滾,發送成功執行commit。

信道發出去的消息會被指派一個惟一ID,消息路由到隊列後,隊列會返回Ack信息其中包含惟一ID,打到確認目的,若是沒能處理此消息,會返回NAck,以後進行重試操做。

隊列爲防止丟數據,通常開啓磁盤持久化,能夠在confirm持久化磁盤後返回ack,這樣保證了消息的持久化。

  • queue設置爲durable爲true,表示持久化隊列
  • 發送消息時將deliveryMode = 2

消費者能夠採用自動確認模式,確認後當即刪除,爲解決丟失數據後,重複消費,能夠關閉自動確認,採用手動確認。

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,而後控制消費者順序消費。

相關文章
相關標籤/搜索