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 總結
沒有完美複制方案,要根據業務需求,評估高性能、高可用和一緻性。