天天看點

RocketMQ/Kafka等消息隊列複制的最佳實踐1 消息複制的名額2 RocketMQ複制3 Kafka 複制4 總結

MQ

  • 在Pro、Con端,依靠業務代碼,配合請求确認機制保證
  • 在服務端,采用持久化和複制

保證不會丢消息。

把消息複制到多節點,可

  • 解決丢消息問題
  • 保證消息服務的HA

是以都會把MQ配置成叢集模式,并開啟消息複制。

那麼消息複制需要解決哪些問題呢?

1 消息複制的名額

期望MQ具備高性能、高可用和資料一緻性。很多MQ都聲明這些特性全部支援,但都有前置條件。

1.1 性能

無論采用哪種複制,都需資料被寫到多節點後再傳回,性能一定不如隻寫入一個節點。

需要寫入節點越多,可用性和資料可靠性越好,但寫性能就越低。

不過,複制對消費的性能影響不大,不管采用哪種複制方式,消費消息時,都隻選擇多副本中一個的節點去讀,和單節點消費無異。

1.2 一緻性

MQ對資料一緻性要求包括:

不丢消息

嚴格順序

若要確定資料一緻性,必須采用主從複制。

主從模式下,資料先寫到主節點,從節點隻從主節點上複制,若出現主從資料不一緻,須以主節點資料為準。

這裡的主節點并非不可變,在很多複制實作中,當主節點出現問題,其他節點可通過選舉,變成主節點。隻要保證,在任一時刻,叢集的主節點數不能超過1個,即可確定資料一緻性。

1.3 高可用

須采用主從複制,高可用需解決的就是,當某個主節點當機,盡快再選個主節點來繼位。

下面看通用的分布式系統設計實作方案:

1.3.1 實作方式

1.3.1.1 管理服務

使用三方服務管理這些節點,發現某主節點當機,由管理服務指定一個新的主節點。

但引入服務會帶來一系列問題,比如管理服務本身的高可用、資料一緻性如何保證?就如 redis 哨兵。

1.3.1.2 自選舉

有的MQ選擇自選舉,由存活節點投票選舉新的主節點。

  • 優點

    無外部依賴,自我管理

  • 缺點

    投票的實作算法都複雜,且選舉過程較慢,幾s至幾十s,在選出新主節點前,服務一直不可用。

  • 大部分複制實踐,都不會選擇把消息寫入全部副本再傳回确認,因為這樣雖可保證資料一緻性,但一旦這些副本中有任一當機,寫入就會卡死。

若隻把消息寫入部分副本就認為寫入成功并傳回确認,即可避免卡死且性能好些。

那寫入多少個副本算寫入成功?假設叢集采用1主2從3副本:

若要求消息寫入2副本算就成功,則3副本最多允許當機1個,否則無法提供服務

若要求寫1副本,隻要消息寫入到主節點就算成功,那3副本可允許當機2個,系統依然可服務,可用性更好

但可能主節點有部分消息還沒及時複制到任一從節點,主節點當機了,這時就會丢消息,資料一緻性失去保證。

不同MQ選擇不同複制實作,有各自優缺點。

2 RocketMQ複制

2.1 傳統複制

RocketMQ複制的基本機關是Broker,服務端程序。采用主從複制,通常配置成一主一從,也支援一主多從。

2.1.2 複制方式

異步複制

消息先發送到主節點,就傳回“寫入成功”,然後再把消息異步複制到從節點。

同步雙寫

消息同步雙寫到主從節點,主從都寫成功,才傳回“寫入成功”。

這兩種方式差別是 寫入多少副本再傳回寫入成功 :

異步複制需副本數1

同步雙寫需副本數2

若在傳回“寫入成功”前,需要寫入的副本數不夠多,就會丢消息。

那RocketMQ采用異步複制會不會丢消息?不會。

為何不會丢消息?

RocketMQ的Broker主從關系通過配置固定,不支援動态切換。

若主節點當機,生産者就不能再生産消息,消費者可自動切換到從節點繼續消費。

這時,即使有一些消息沒來得及複制到從節點,這些消息依然躺在主節點磁盤,除非主節點磁盤壞了,否則等主節點重新恢複服務,這些消息依然可繼續複制到從節點,也可繼續消費,不會丢消息,消息順序也沒問題。

這種主從複制方式,通過犧牲可用性,得到較好的性能和資料一緻性。

可用性

一對主從節點可用性不行,那就多對。

  • 功能

    RocketMQ支援把一個主題分布到多對主從節點,每對主從節點中承擔主題中的一部分隊列。

  • 表現

    若某主節點當機,自動切換到其他主節點繼續發消息。

  • 解決如下問題:
    • 還可通過水準擴容提升Topic性能

舊複制缺陷

由于topic層無法保證嚴格順序,必須指定隊列發消息,對任一隊列,一定是落在一組特定主從節點,若該主節點當機,其他主節點無法替代這主節點,否則就無法保證嚴格順序。

是以這種複制模式的嚴格順序和高可用隻能選其一。

2.2 新複制

2018年底引入Deldger,一種全新複制方式。

Dledger在寫入消息時,要求至少消息複制到半數以上節點後,才給用戶端傳回寫成功,且支援選舉動态切換主節點。

執行原理

3節點為例。

  • 當主節點當機,2從節點會通過投票選出1新主節點,相比主從複制,解決了可用性
  • 由于消息要至少複制到2節點才傳回寫成功,即使主節點當機,也至少有一節點消息是和主節點一緻。選舉時,總會把資料和主節點一樣的從節點選為新主,保證了資料一緻性,既不會丢消息,還可保證嚴格順序。

  • 選舉過程中不能提供服務
  • 至少需3節點才能保證資料一緻性
  • 3節點時,隻能保證1節點當機時可用,若2個節點同時當機,即使還有1個節點存活也無法提供服務,資源使用率較低
  • 由于至少要複制到半數以上的節點才傳回寫入成功,不如主從異步複制快

3 Kafka 複制

複制的基本機關是分區。每個分區的幾個副本間構成一個小複制叢集。

Broker隻是這些分區副本的容器,是以Kafka的Broker不分主從。

分區的多個副本中采用一主多從。

寫入消息時,異步複制。消息在寫到主節點後,并不會馬上傳回寫入成功,而是等待足夠多節點都複制成功後再傳回。

“足夠多”由使用者定。對應:ISR(In Sync Replicas),“保持資料同步的副本”。ISR的數量可配,ISR中包含主節點。

Kafka使用ZooKeeper監控每個分區的多節點,發現某分區主節點當機:

Kafka會利用ZooKeeper選個新主節點,這解決可用性

選舉時,會從所有ISR節點選新主節點,這保證資料一緻性

預設如果所有ISR當機,分區就無法提供服務。也可以選擇配置成讓分區繼續提供服務,這樣隻要有一個節點活,就可提供服務,代價是無法保證資料一緻性,會丢消息。

Kafka的這種高度可配置的複制方式

非常靈活,可自定義配置這些複制參數,在可用性、性能和一緻性這幾方面做業務取舍

學習成本較高

4 總結

沒有完美複制方案,要根據業務需求,評估高性能、高可用和一緻性。

繼續閱讀