前言
小夥伴們,通過前邊文章的閱讀,相信大家已經對RocketMQ的基本原理有了一個比較深入的瞭解,那麼大家對當前比較常用的RabbitMQ和Kafka是不是也有興趣瞭解一些呢,瞭解的多一些也不是壞事,面試或者跟人聊技術的時候也會讓你更有話語權嘛。
那王子今天就跟大家聊一聊RabbitMQ和Kafka在處理高可用叢集時的原理,看看它們與RocketMQ有什麼不同。小夥伴們可以重新溫習一下常見的訊息中介軟體有哪些?你們是怎麼進行技術選型的?這篇文章,瞭解一下他們之間的區別。
RabbitMQ的高可用
之前我們的文章講過,RabbitMQ是ActiveMQ的一個很好的替代產品,它是基於主從實現的高可用叢集,但它是非分散式的。
RabbitMQ一共有三種模式:單機模式、普通叢集模式、映象叢集模式。
單機模式沒什麼可說的,自己開發練手玩玩就行,我們主要說一下兩種叢集模式的區別。
普通叢集模式
普通叢集模式,其實就是將RabbitMQ 部署到多臺機器上,每個機器啟動一個,它們之間進行訊息通訊。你建立的 queue,只會放在一個 RabbitMQ 的例項上,其他的例項會同步 queue 的後設資料(後設資料裡包含有 queue 的一些配置資訊,通過後設資料,可以找到 queue 所在的位置)。你消費的時候,實際上如果連線到了另外一個例項,那麼那個例項會通過後設資料定位到 queue 所在的位置,然後訪問queue所在的例項,拉取資料過來傳送給消費者。
整體過程見下圖:
這種方式很麻煩,只是一個普通的叢集,而且資料並沒有副本,只儲存在了一臺機器上,只要真實儲存資料的機器當機,系統直接崩潰,因為沒有資料可以獲取了。
所以可以得出一個結論,這種模式的叢集根本不能實現高可用,只能通過負載均衡提高一些MQ的吞吐量,生成環境下是不會使用的。
映象叢集模式
那麼真正用於生產環境,實現高可用的方式是什麼呢?沒錯就是接下來要說的映象叢集模式。
它和普通叢集模式最大的區別在於,queue資料和原資料不再是單獨儲存在一臺機器上,而是同時儲存在多臺機器上。也就是說每個RabbitMQ例項都有一份映象資料(副本資料)。每次寫入訊息的時候都會自動把資料同步到多臺例項上去,這樣一旦其中一臺機器發生故障,其他機器還有一份副本資料可以繼續提供服務,也就實現了高可用。
整個過程看下圖:
那麼如何開啟映象叢集模式呢?
RabbitMQ是有強大的管理控制檯的,通過管控臺可以很容易的配置,具體操作自行百度吧,我們本篇的目的是弄懂原理。
對於一般小型公司,小型專案來講,這套架構已經可以支援了,但是對於海量大資料的要求,如果每臺機器都要有一份映象副本,而且互相之間還要不停的同步資料,它是很難支援的,因為它不是分散式的。所以我們還是使用RocketMQ吧。
Kafka的高可用
再來聊聊Kafka的高可用,再聊高可用之前,我們先要簡單瞭解下它的基本架構。
它是由多個Broker組成的,每個Broker都是一個節點,小夥伴們是不是想到了RocketMQ的Broker呢。當我們建立Topic的時候,這個Topic是會劃分成多個partition的,每個partition又可以存在不同的Broker上,這裡的每個partition都會放一部分資料,可以把它理解成一個分片。
由此可見,Kafka是一個天然的分散式訊息佇列,它的Topic是分成多個partition分佈到多個Broker上儲存的。
既然講到這裡,可能有很多小夥伴會好奇RocketMQ的Topic是怎麼儲存的呢?難道RocketMQ的Topic就不會分片了嗎?
答案是否定的,RocketMQ也是借鑑了Kafka分片儲存的機制,引入了一個新的概念ConsumeQueue用來代替partition,原先kafka,裡面partition儲存的是整個訊息,但是現在ConsumeQueue裡面是儲存訊息的儲存地址,但是不儲存訊息了。現在每個ConsumeQueue儲存的是每個訊息在commitlog這個檔案的地址,但是訊息存在於commitlog中。
也就是所有的訊息體都寫在了一個檔案裡面,每個ConsumeQueue只是儲存這個訊息在commitlog中地址。
好了,有關RocketMQ的原理我們之後再單獨講解,現在我們繼續看Kafka的高可用實現。
Kafka 0.8 以後,才正式開始支援高可用的,它提供了 HA 機制,就是 replica(複製品) 副本機制。每個 partition 的資料都會同步到其它機器上,形成自己的多個 replica 副本。所有 replica 會選舉一個 leader 出來,那麼生產和消費都跟這個 leader 打交道,然後其他 replica 就是 follower。寫的時候,leader 會負責把資料同步到所有 follower 上去,讀的時候就直接讀 leader 上的資料即可。只能讀寫 leader?很簡單,要是你可以隨意讀寫每個 follower,那麼就要 考慮資料一致性的問題,系統複雜度太高,很容易出問題。Kafka 會均勻地將一個 partition 的所有 replica 分佈在不同的機器上,這樣才可以提高容錯性。
我們看一下下圖,就是Kafka的高可用原理:
這樣的一套架構下,Kafka就實現高可用了。因為如果某個Broker掛掉了,他的partition在其他Broker中都有副本。如果掛掉的Broker上有某個 partition 的 leader,那麼此時會從 follower 中重新選舉一個新的 leader 出來,大家繼續讀寫那個新的 leader 即可。這就有所謂的高可用性了。
寫資料的時候,生產者就向 leader寫資料,然後 leader 將資料落地寫本地磁碟,接著其他 follower 自己主動從 leader 來 pull 資料。一旦所有 follower 同步好資料了,就會傳送 ack 給 leader,leader 收到所有 follower 的 ack 之後,就會返回寫成功的訊息給生產者。(當然,這只是其中一種模式,還可以適當調整這個行為)
消費的時候,只會從 leader 去讀,但是隻有當一個訊息已經被所有 follower 都同步成功返回 ack 的時候,這個訊息才會被消費者讀到。
總結
好了,說了這麼多,我相信小夥伴們對於RabbitMQ和Kafka的高可用叢集原理一定會有個很深的認識了吧。那王子給大家留下一個思考題,現在你能自己說出RabbitMQ、Kafka、RocketMQ的高可用叢集有什麼不同了嗎?
今天的分享就到這裡,歡迎大家持續閱讀王子的訊息中介軟體專輯,一起閒談訊息中介軟體的裡裡外外吧。
往期文章推薦:
中介軟體專輯:
演算法專輯: