消息中間件該如何實現高可用架構?

語言: CN / TW / HK

1. 背景引入 

這篇文章,我們來聊一下消息中間件高可用架構的一些原理。

對於一個合格的高級 Java 工程師而言,你肯定會碰到在系統裏用到 MQ(消息隊列)的場景。那麼這個時候你需要基於你的業務場景和需求,考慮在使用 MQ 的時候可能遇到的一些技術問題。

接着,你必須得針對這些技術問題設計一套完整的技術方案。

你需要從 消息的訂閲模式 消息的生產到消費全鏈路不丟數據 消息中間件本身如何保證高可用 等各個角度切入,來考慮好你的系統和 MQ 對接之後的完整技術方案。

所以,本文就來聊聊消息中間件高可用的架構原理。

2. 先來思考一下消息中間件的可用性問題 

咱們先拋開各種具體的技術,思考一下什麼是 MQ 的可用性問題?

大家看看下面的圖,其實道理很簡單。假設你的 MQ 就部署在一台機器上,那麼正常情況下,生產者都會發送消息到 MQ 去,然後讓消費者獲取到。

但是萬一天有不測風雲,MQ 部署的那台機器因為一些莫名的原因 MQ 自己本身的進程掛掉了或者是那台機器直接就宕機了,那麼這種時候該怎麼辦呢?

很尷尬,是不是?結果是很明顯的。生產者沒法發送數據出去,然後消費者也沒法獲取到數據了。

然後整個系統不就完蛋了?因為系統的核心流程根本無法跑通了,對不對?

MQ 宕機就直接導致你的系統本身也故障了,然後可能會導致你的公司對外的 App、網站等產品就無法運作了,用户無法使用你們公司的服務了。

如果你們公司是電商平台、外賣平台、社交平台。那麼來這麼一出,不是會導致公司損失慘重?

如果你的系統持續幾個小時無法被人使用,本來你公司電商平台一天營收可以達到 1 億,結果現在導致幾個小時內無法下單購買商品,最後當天營收就 5000 萬,那麼你的公司是不是直接活生生損失了 5000 萬?

這個真的不是開玩笑的,如果大家留意互聯網行業的新聞的話和小道消息的話,就應該知道近幾年一些大型互聯網公司都出現過類似的情況,損失慘重。咱們做碼農的就得被祭天了,是不是?

3. 集羣化部署 + 數據多副本宂餘

好,問題來了!現在你感覺一個 MQ 中間件應該如何實現高可用呢?

這裏的方式有很多種,比如説 數據多副本宂餘 集羣鏡像同步機制 。我們就拋開具體的技術來從本質層面思考一下 MQ 集羣實現高可用的幾種方式。

先來看下面的一張圖,假設我們寫到 MQ 的數據都被多副本宂餘了,也就是你寫的每一條消息都被複制到了其他的機器上去了。

那麼此時任何一台機器宕機,似乎都不會影響我們跟 MQ 繼續通信,而且寫出去的數據似乎也都還在。

上面的圖裏,MQ 採用集羣模式部署到了兩台機器上去,然後生產者給其中一台機器寫入一條消息,該機器自動同步複製給另外一台機器。

此時數據在兩台機器上,就有兩個副本了。那麼如果第一台機器宕機了,會影響我們嗎?

答案是: 不會

因為數據本身是多副本宂餘的,此時消費者完全可以從第二台機器消費到這條消息,並且生產者還可以繼續給第二台機器寫入消息,數據沒丟失。

而且,系統根本不用中斷流程,還可以繼續運行,我們看下面的圖。

這種感覺是不是很棒?實際上這種 MQ 集羣化部署架構以及數據多副本宂餘機制,是非常常見的一種高可用架構。

Kafka 這個極為優秀的消息中間件,就是採用的這種架構保證高可用、數據容錯性。

4. 多副本同步複製強制要求 

但是這裏你要思考另外幾個問題。

第一個問題,你在寫數據到其中一台機器的時候,是不是有這樣的要求:必須得讓那台機器複製數據到另外一台機器了,保證集羣裏一定有這條數據雙副本了,才可以認為本次寫成功了?

沒錯,假如你要是不能保證這一點,比如你就寫數據給了其中一台機器,然後它還沒來得及複製給另外一台機器呢,直接第一台機器就宕機了。

此時,雖然你可以繼續基於第二台機器發送消息和消費消息,但是你剛才發送的一條消息就丟失了。

大家看下面的圖來理解一下這個場景。

所以對於採用這種機制的時候,你必須得讓生產者通過一些參數的設置,保證寫一條消息到某台機器,必須同步這條消息到另外一台機器成功。等到集羣裏有雙副本了,然後才可以認為這條消息寫成功了。

只要剛寫一台機器他就宕機,還沒來得及複製到另外一台機器的話,本次寫應該報錯失敗。然後,你應該重試再次寫入數據到 MQ 集羣裏去。

大家看看下面的圖。只要你一次寫成功了,就保證肯定已經同步數據為雙副本了。此時,哪怕一台機器宕機,數據不會丟失,生產和消費都可以有條不紊地繼續進行。

5. 多機器承載多副本強制要求 

第二個問題,假如説現在你的集羣中本來有兩台機器,現在其中的一台 宕機了 ,只有一台機器了,你還能允許你的生產者對唯一的那台機器繼續寫入數據嗎?

答案是:

因為,如果集羣裏只有一台機器可以承載寫入,那麼萬一剩餘的一台機器又宕機了呢?是不是還是會導致數據丟失,集羣完蛋?

所以説,你的生產者同理應該基於參數設置一下,集羣裏必須有超過兩台機器可以接收你的數據副本複製。

否則如果只有一台機器可以接受你的數據副本複製的話,那麼還是算了。

大家看看下面的圖,感受一下那個場景。

假設集羣裏有 3 台機器,那麼其中一台宕機了,你後續再寫入另外一台的時候,判斷一下集羣裏還有剩餘兩台機器,足以保證數據雙副本的高可用性和容錯性,所以可以繼續正常的寫入數據到 MQ 集羣裏去。

實際上,上面説的那一整套的機制,在 Kafka 裏都可以採用。它有對應的一些參數可以配置數據有幾個副本,包括你每次寫入必須複製到幾台機器才可以算成功,否則就要重新發送。還可以通過參數設置,集羣剩餘機器必須可以承載幾個副本才能繼續寫入數據。

通過這一整套方案的設計和基於具體技術的落地,才可以保證在集羣化部署的情況下,集羣必須有幾台機器承載多副本,同時數據寫入之後必須是保證多副本宂餘的。

此時,任何機器宕機,數據都不會丟失,還可以正常讓系統繼續運行。

6. 架構原理與技術無關性  

其實本文對消息中間件的集羣高可用架構的探討,是完全脱離於某個具體技術的,非常樸素的從本質的原理層面來討論這個話題。

具體的 RabbitMQ、Kafka、RocketMQ 等各種不同的消息中間件,對這種高可用架構的實現,都有一定的相似想通性,但是也都有各自不同的技術實現,以及相對應的區別。

- EOF -

看完本文有收穫?請轉發分享給更多人

關注「ImportNew」,提升Java技能

點贊和在看就是最大的支持:heart: