1. 程式人生 > >RabbitMQ 和 Kafka 到底怎麼選?

RabbitMQ 和 Kafka 到底怎麼選?

前言


開源社群有好多優秀的佇列中介軟體,比如RabbitMQ和Kafka,每個佇列都貌似有其特性,在進行工程選擇時,往往眼花繚亂,不知所措。對於RabbitMQ和Kafka,到底應該選哪個?

 

RabbitMQ架構


RabbitMQ是一個分散式系統,這裡面有幾個抽象概念。

  • broker:每個節點執行的服務程式,功能為維護該節點的佇列的增刪以及轉發佇列操作請求。

  • master queue:每個佇列都分為一個主佇列和若干個映象佇列。

  • mirror queue:映象佇列,作為master queue的備份。在master queue所在節點掛掉之後,系統把mirror queue提升為master queue,負責處理客戶端佇列操作請求。注意,mirror queue只做映象,設計目的不是為了承擔客戶端讀寫壓力。

如上圖所示,叢集中有兩個節點,每個節點上有一個broker,每個broker負責本機上佇列的維護,並且borker之間可以互相通訊。叢集中有兩個佇列A和B,每個佇列都分為master queue和mirror queue(備份)。那麼佇列上的生產消費怎麼實現的呢?訊息佇列的應用場景可以看這篇文章《訊息佇列常見的幾種使用場景介紹》

 

佇列消費


如上圖有兩個consumer消費佇列A,這兩個consumer連在了叢集的不同機器上。RabbitMQ叢集中的任何一個節點都擁有叢集上所有佇列的元資訊,所以連線到叢集中的任何一個節點都可以,主要區別在於有的consumer連在master queue所在節點,有的連在非master queue節點上。

因為mirror queue要和master queue保持一致,故需要同步機制,正因為一致性的限制,導致所有的讀寫操作都必須都操作在master queue上(想想,為啥讀也要從master queue中讀?和資料庫讀寫分離是不一樣的。),然後由master節點同步操作到mirror queue所在的節點。即使consumer連線到了非master queue節點,該consumer的操作也會被路由到master queue所在的節點上,這樣才能進行消費。

 

佇列生產


原理和消費一樣,如果連線到非 master queue 節點,則路由過去。

所以,到這裡小夥伴們就可以看到 RabbitMQ的不足:由於master queue單節點,導致效能瓶頸,吞吐量受限。雖然為了提高效能,內部使用了Erlang這個語言實現,但是終究擺脫不了架構設計上的致命缺陷。

 

Kafka


說實話,Kafka我覺得就是看到了RabbitMQ這個缺陷才設計出的一個改進版,改進的點就是:把一個佇列的單一master變成多個master,即一臺機器扛不住qps,那麼我就用多臺機器扛qps,把一個佇列的流量均勻分散在多臺機器上不就可以了麼?注意,多個master之間的資料沒有交集,即一條訊息要麼傳送到這個master queue,要麼傳送到另外一個master queue。

這裡面的每個master queue 在Kafka中叫做Partition,即一個分片。一個佇列有多個主分片,每個主分片又有若干副分片做備份,同步機制類似於RabbitMQ。

如上圖,我們省略了不同的queue,假設叢集上只有一個queue(Kafka中叫Topic)。每個生產者隨機把訊息傳送到主分片上,之後主分片再同步給副分片。

佇列讀取的時候虛擬出一個Group的概念,一個Topic內部的訊息,只會路由到同Group內的一個consumer上,同一個Group中的consumer消費的訊息是不一樣的;Group之間共享一個Topic,看起來就是一個佇列的多個拷貝。所以,為了達到多個Group共享一個Topic資料,Kafka並不會像RabbitMQ那樣訊息消費完畢立馬刪除,而是必須在後臺配置儲存日期,即只儲存最近一段時間的訊息,超過這個時間的訊息就會從磁碟刪除,這樣就保證了在一個時間段內,Topic資料對所有Group可見(這個特性使得Kafka非常適合做一個公司的資料匯流排)。佇列讀同樣是讀主分片,並且為了優化效能,消費者與主分片有一一的對應關係,如果消費者數目大於分片數,則存在某些消費者得不到訊息。

由此可見,Kafka絕對是為了高吞吐量設計的,比如設定分片數為100,那麼就有100臺機器去扛一個Topic的流量,當然比RabbitMQ的單機效能好。

 

總結


本文只做了Kafka和RabbitMQ的對比,但是開源佇列豈止這兩個,ZeroMQ,RocketMQ,JMQ等等,時間有限也就沒有細看,故不在本文比較範圍之內。

所以,別再被這些五花八門的佇列迷惑了,從架構上找出關鍵差別,並結合自己的實際需求(比如本文就只單單從吞吐量一個需求來考察)輕輕鬆鬆搞定選型。最後總結如下:

  • 吞吐量較低:Kafka和RabbitMQ都可以。

  • 吞吐量高:Kafka。

本文內容參考自RabbitMQ和KafKa官方文件,所以真要搞懂一箇中間件的原理最好去看官方文件,文件裡面有詳細的設計方案,我們可以自己進行設計方案的對比,從而找出符合自己實際情況的中介軟體。