1. 程式人生 > >分布式開發之消息隊列

分布式開發之消息隊列

分享圖片 隊列 發生 模式 bubuko 有一個 mem 插入數據 需要

本文圍繞如下幾點進行闡述:

  1. 為什麽使用消息隊列?
  2. 使用消息隊列有什麽缺點?
  3. 消息隊列如何選型?
  4. 如何保證消息隊列是高可用的?
  5. 如何保證消息不被重復消費?
  6. 如何保證消費的可靠性傳輸?

1. 為什麽使用消息隊列?

解耦,異步,限流

2. 使用消息隊列有什麽缺點?

導致系統可用性降低,若MQ發生故障會影響系統可用性。系統復雜性增加,引入MQ會引入新的關註點,比如需要考慮消息可靠性投遞,消息重復消費等問題。

3. 消息隊列如何選型?

1. 看MQ更新頻率

2. 看MQ性能

3. 比較MQ各自特點,比如Kafka適合大數據場景如日誌采集

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

以RcoketMQ為例,他的集群就有多master 模式、多master多slave異步復制模式、多 master多slave同步雙寫模式。多master多slave模式部署架構圖:

技術分享圖片

Rocket的高可用架構和kafka很像,只是NameServer集群,在kafka中是用zookeeper代替,都是用來保存和發現master和slave用的。通信過程如下:
Producer 與 NameServer集群中的其中一個節點(隨機選擇)建立長連接,定期從 NameServer 獲取 Topic 路由信息,並向提供 Topic 服務的 Broker Master 建立長連接,且定時向 Broker 發送心跳。Producer 只能將消息發送到 Broker master,但是 Consumer 則不一樣,它同時和提供 Topic 服務的 Master 和 Slave建立長連接,既可以從 Broker Master 訂閱消息,也可以從 Broker Slave 訂閱消息。

kafka:

技術分享圖片

如上圖所示,一個典型的Kafka集群中包含若幹Producer(可以是web前端產生的Page View,或者是服務器日誌,系統CPU、Memory等),若幹broker(Kafka支持水平擴展,一般broker數量越多,集群吞吐率越高),若幹Consumer Group,以及一個Zookeeper集群。Kafka通過Zookeeper管理集群配置,選舉leader,以及在Consumer Group發生變化時進行rebalance。Producer使用push模式將消息發布到broker,Consumer使用pull模式從broker訂閱並消費消息。

5. 如何保證消息不被重復消費?

其實無論是那種消息隊列,造成重復消費原因其實都是類似的。正常情況下,消費者在消費消息時候,消費完畢後,會發送一個確認信息給消息隊列,消息隊列就知道該消息被消費了,就會將該消息從消息 隊列中刪除。只是不同的消息隊列發送的確認信息形式不同,例如RabbitMQ是發送一個ACK確認消息,RocketMQ是返回一個CONSUME_SUCCESS成功標誌,kafka實際上有個offset的概念,簡單說一下(如果還不懂,出門找一個kafka入門到精通教程),就是每一個消息都有一個offset,kafka消費過消息後,需要提交offset,讓消息隊列知道自己已經消費過了。那造成重復消費的原因?,就是因為網絡傳輸等等故障,確認信息沒有傳送到消息隊列,導致消息隊列不知道自己已經消費過該消息了,再次將該消息分發給其他的消費者。

1. 利用數據庫主鍵唯一性:全局唯一ID + 指紋碼。當唯一ID插入數據庫時會因為主鍵約束而失敗,這樣就能保障消息不會被重復消費。

2. 利用redis的原子性。但也有需要考慮的問題。如何消息落地。

6.如何保障消費的可靠性傳輸。

可靠性傳輸要從三個角度來分析:生產者弄丟數據、消息隊列弄丟數據、消費者弄丟數據

6.1 生產端的可靠性投遞

保障消息的成功發出,保障MQ節點的成功接收,發送端收到MQ節點確認應答。完善的消息進行補償機制。

6.1.1 解決方案

6.1.1.1 消息落庫,對消息狀態進行打標。

技術分享圖片

6.1.1.2 消息的延遲投遞,做二次確認,回調檢查。

技術分享圖片

6.2 MQ消息隊列丟數據
處理消息隊列丟數據的情況,一般是開啟持久化磁盤的配置。這個持久化配置可以和confirm機制配合使用,你可以在消息持久化磁盤後,再給生產者發送一個Ack信號。這樣,如果消息持久化磁盤之前,rabbitMQ陣亡了,那麽生產者收不到Ack信號,生產者會自動重發。
   那麽如何持久化呢,這裏順便說一下吧,其實也很容易,就下面兩步
   1、將queue的持久化標識durable設置為true,則代表是一個持久的隊列
   2、發送消息的時候將deliveryMode=2
  這樣設置以後,rabbitMQ就算掛了,重啟後也能恢復數據

6.3 消費者丟數據
消費者丟數據一般是因為采用了自動確認消息模式。這種模式下,消費者會自動確認收到信息。這時RabbitMQ會立即將消息刪除,這種情況下如果消費者出現異常而沒能處理該消息,就會丟失該消息。
至於解決方案,采用手動確認消息即可。

未完待續

分布式開發之消息隊列