1. 程式人生 > >RabbitMQ與Kafka選型對比

RabbitMQ與Kafka選型對比

背景

  本公司是.Net專案,在.Net可選的MQ比較少,主要Kafka和RabbitMQ,RabbitMQ我也是使用多年了,最近的Kafka廣告與流行度我也是無法無視,因此也是花了點時間收集了資料做了些對比。

  此外有個小插曲,當我形成了文件讓老闆兼CTO對比決策後,他打算上阿里雲買MQ服務。我當時給他開了個玩笑:您這價錢把我請回來,而且公司還有運維,其實完全可以自己維護,要不我來負責,你把這每個月的MQ費用給我加工資得了。當我下樓買了支維他檸檬茶後,他決定由我們自己搭建RabbitMQ。這個決定跟我的想法差不多,原因主要兩點:運維起來方便,吞吐沒有特別高。

  如果下文有總結不到位的,或者差錯的,可以在下方評論反饋給我

RabbitMQ模型

名詞 描述
Queue 用於儲存訊息,消費者直接繫結Queue進行消費訊息
Exchange 生產者將訊息傳送到Exchange,由交換器將訊息通過匹配Exchange Type、Binding Key、Routing Key後路由到一個或者多個佇列中。
Exchange Type Direct、Fanout、Topic、Headers
Routing Key 生產者傳送訊息給Exchange會指定一個Routing Key。
Binding Key 在繫結Exchange與Queue時會指定一個Binding Key

  1.Exchange在宣告時會繫結Queue和Binding Key,當Exchange收到訊息會根據訊息的

  2.Routing Key與Exchange Type、Binding Key進行匹配,最後會路由到相關的隊列當中。

     Fanout,將訊息傳送到與該交換器所繫結的所有佇列中,與Routing Key、Bind Key無關,這就是廣播模式。

     Topic,通過對訊息的Routing Key和Exchange、Queue進行匹配,將訊息路由給一個或多個佇列,以此來達到釋出/訂閱模式。

   Direct,把訊息路由到哪些Bind Key和Routing Key完全匹配的佇列中。

   Headers,不依賴與路由鍵的匹配規則,基本用不上。

  3.消費者會直接訂閱Queue裡的訊息進行消費,多個消費者訂閱同個Queue會形成訊息競爭狀態,以此達到負載均衡作用。

Kafka模型

 

名詞 描述
Topic 佇列是通過Topic進行隔離的,生產者傳送訊息必須指定Topic
Broker 一個Kafka Server的被稱為一個Broker。
Partition 每個Topic可以包含多個Partition,多個Partition會平均分配給同一個Consumer Group裡的不同Consumer進行消費
Consumer Group 不在同一個Group 的Consumer能重複消費同一條訊息(訂閱),相同Group的Consumer存在消費競爭(負載均衡)
  1. Kafka與RabbitMQ比沒有Exchange的概念,生產者直接發訊息Topic(佇列)。
  2. Kafka的訂閱者是通過消費組(Consumer Group)來體現的,每個消費組都可以重複消費Topic一份完整的訊息,不同消費組之間消費進度彼此不受影響。例如Message1能被Consumer Group 1和Consumer Group2裡的消費者都消費一次。
  3. 消費組中包含多個消費者,同個Group的消費者之間是競爭消費的關係。例如Message2只能夠被Consumer Group裡某一個Consumer只消費一次。
  4. Kafka具有訊息儲存的功能,訊息被消費後不會被立即刪除,因為需要被不同的Consumer Group多次消費同個訊息,因此會在Topic維護一個Consumer Offset,每消費成功Offset自增1.

功能對比

 

對比項 RabbitMQ Kafka
吞吐量
有序性 全域性有序性 分割槽有序性
訊息可靠性 多策略組合 訊息持久化
流處理 不支援 支援
時效性
運維便捷度
系統依賴 zookeeper
Web監控 自帶 第三方
優先順序佇列 支援 不支援
死信 支援 不支援
客戶端支援 支援多種語言
社群生態
安全機制 (TLS/SSL、SASL)身份認證和(讀寫)許可權控制
訊息回溯 支援 不支援

 

對比描述

共同點

RabbitMQ與Kafka都有很好的客戶端語言支援、安全機制與生態支援。

效能

Kafka的誕生的是處理高併發日誌的,吞吐量比較高,每秒請求數達到數十萬量級,而RabbitMQ每秒請求數則為萬級別,有測試報告指出Kafka是RabbitMQ的10倍以上效能。

運維便捷

RabbitMQ相對比較方便,可以使用yum或者docker安裝,自帶Web管理UI,沒有額外的依賴,除了需要做映象佇列外需要引入HAproxy。

Kafka則需要依賴Zookeeper,也沒有自帶的管理工具,可以使用第三方的Kafka Eagle代替,Kafka Manager過於難用,另外Kafka沒有yum安裝,docker映象也是社群人員自己建的。

有序性

RabbitMQ理論上是全域性有序性的,但是由於【發後既忘】+【自動確認】機制的原因,如果在同個佇列的多個消費者做相同的業務處理時,他們的各自的執行任務無法保證有序完成。如果確保100%有序可以使用【非自動確認】,但會影響消費效能。

Kafka支援分割槽有序性,如果對有序性有嚴格要求可以設定單個Partition,可是單個Partition併發性比較低,因此在多個Partition情況下可以根據業務指定key把相關的訊息路由到同一個Partition,例如相同UserId行為資訊可以到Partition 1進行處理。

時效性

Kafka基本上無論在客戶端還是服務端都是以【非同步批量】的機制進行處理,通俗的講就是先攢起來一堆訊息,到了某個閥值再發送,也會導致一些訊息可靠性與訊息有時效上的問題,當然可以通過各種配置策略進行解決。

訊息回溯

Kafka在消費完了訊息後不會立即刪除,只會修改offset,如果之前部分業務消費失敗了可以重新設定offset進行重新消費。

RabbitMQ則是[發後既忘]的機制,一但消費者確認訊息則刪除,但是可以通過死信進行補償消費。此外RabbitMQ在佇列訊息堆積多的情況下效能表現不佳,所以儘可能的及時消費訊息。

特色功能

RabbitMQ具有死信的功能,可以通過死信形成重複消費與延時傳送。

Kafka具有流處理功能,可以收集使用者的行為日誌進行儲存與分析。

Kafka為什麼快?

關鍵核心技術點:

  • 非同步批量處理
  • 磁碟順序讀寫
  • 作業系統PageCache快取資料
  • 零拷貝加速消費

Kafka的誕生就是為了高併發日誌處理的,那麼在他整個機制裡使用了很多批量、非同步、快取。例如生產者客戶端,他會積累一定量(條數、大小)的訊息,再批量的發給kafka broker,如果在這段時間客戶端服務掛了,就等於訊息丟失了。當broker接受到了訊息後,還有一堆騷操作-非同步刷盤,也就是生產者傳送給broker之後他是記錄在快取的,每隔一段時間才會持久化到磁碟,假如這段真空期broker掛了,訊息也是丟了。

Kafka是否訊息不可靠?

Kafka快是因為犧牲了訊息可靠換取回來的效能,在最早期版本的確沒提供訊息可靠的策略,經過多個版本迭代後的功能完善,已經不存在這種舊觀念。那麼可靠的關鍵點有以下:

生產者

設定ack:

  • 0:producer不等待broker的ack,broker一接收到還沒有寫入磁碟就已經返回,可靠性最低;
  • 1:producer等待broker的ack,partition的leader刷盤成功後返回ack,如果在follower同步成功之前leader故障,那麼將會丟失資料,可靠性中;
  • -1:producer等待broker的ack,partition的leader和follower全部落盤成功後才返回ack,資料一般不會丟失,延遲時間長但是可靠性高

消費者

設定enable.auto.commitrue,不管執行結果如何,消費者會自動提交offset。

false,需要使用者需要手動提交offset,可以根據執行結果具體處理offset

RabbitMQ單節點部署

安裝
yum install -y rabbitmq-server

開放相關埠

firewall-cmd --permanent --add-port=15672/tcp
firewall-cmd --permanent --add-port=5672/tcp
firewall-cmd --reload

啟動服務

service rabbitmq-server start

啟動web管理介面

rabbitmq-plugins enable rabbitmq_management

增加訪問admin使用者,預設使用者guest只能本地訪問。

rabbitmqctl add_user admin 123456

設定admin使用者為管理員角色 

rabbitmqctl set_user_tags admin administrator

設定預設admin使用者訪問許可權

rabbitmqctl set_permissions -p "/" admin "." "." ".*"

重啟服務

service rabbitmq-server restart

瀏覽器訪問:http://IP:15672

Kafka單節點部署

Zookeeper部署

下載Zookeeper並啟動

docker run -d --restart always --name zookeeper -p 2181:2181 -v /root/zookeeper/data:/data -v /root/zookeeper/conf:/conf -v /root/zookeeper/logs:/logs zookeeper:3.6.1

開放2181埠

firewall-cmd --permanent --add-port=2181/tcp
firewall-cmd --reload

Kafka服務部署

下載kafka 映象並啟動

docker run -d --name kafka -p 9092:9092 -e KAFKA_BROKER_ID=1 -e KAFKA_ZOOKEEPER_CONNECT=192.168.88.139:2181 -e KAFKA_ADVERTISED_HOST_NAME=192.168.88.141 -e KAFKA_ADVERTISED_PORT=9092 wurstmeister/kafka:2.12-2.5.0

建立目錄並拷貝

mkdir /root/kafka
docker cp kafka:/opt/kafka/config /root/kafka/config

刪除原有的容器並重新建立

docker stop kafka
docker rm kafka

docker run -d --name kafka -p 9092:9092 -e KAFKA_BROKER_ID=1 -e KAFKA_ZOOKEEPER_CONNECT=192.168.88.139:2181 -e KAFKA_ADVERTISED_HOST_NAME=192.168.88.141 -e KAFKA_ADVERTISED_PORT=9092 -v /root/kafka/config: /opt/kafka/config wurstmeister/kafka:2.12-2.5.0

開放9092埠

firewall-cmd --permanent --add-port=9092/tcp
firewall-cmd --reload

Kafka-eagle

下載jdk依賴

yum -y install java-1.8.0-openjdk*

下載kafka-eagle-bin包

wget -o kafka-eagle-bin.tar.gz https://codeload.github.com/smartloli/kafka-eagle-bin/tar.gz/v2.0.1

解壓

tar -zxvf kafka-eagle-bin.tar.gz
tar -zxvf kafka-eagle-bin-2.0.1/kafka-eagle-web-2.0.1-bin.tar.gz
mv kafka-eagle-web-2.0.1 kafka-eagle

新增環境變數

vim /etc/profile

export JAVA_HOME=/usr
export KE_HOME=/etc/kafka-eagle
export PATH=$PATH:$KE_HOME/bin:$JAVA_HOME/bin

生效環境變數

source /etc/profile
修改Kafka-eagle配置
cd /etc/kafka-eagle/conf
vim system-config.properties

#註釋
#cluster2.zk.list=xdn10:2181,xdn11:2181,xdn12:2181
#cluster2.kafka.eagle.offset.storage=zk


#cluster1.zk.acl.enable=false
#cluster1.zk.acl.schema=digest
#cluster1.zk.acl.username=test
#cluster1.zk.acl.password=test123


修改
kafka.eagle.zk.cluster.alias=cluster1
cluster1.zk.list=192.168.88.139:2181
kafka.eagle.metrics.charts=true

kafka.eagle.driver=org.sqlite.JDBC
kafka.eagle.url=jdbc:sqlite:/etc/kafka-eagle/db/ke.db
kafka.eagle.username=root
kafka.eagle.password=root

啟動kafka-eagle服務

cd /etc/kafka-eagle/bin
chmod +x ke.sh
ke.sh start

開啟防火牆

firewall-cmd --permanent --add-port=8048/tcp     
firewall-cmd --reload

瀏覽器訪問:http://IP:8048

阿里雲費用

以下截圖基本以最低配置。

Kafka按量付費

Kafka包月

RabbitMQ包月