訊息中介軟體該如何實現高可用架構?

語言: 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: