背景
java
本公司是.Net項目,在.Net可選的MQ比較少,主要Kafka和RabbitMQ,RabbitMQ我也是使用多年了,最近的Kafka廣告與流行度打得使我也是沒法無視,所以也是花了點時間收集了資料作了些對比。git
此外有個小插曲,當我造成了文檔讓老闆兼CTO對比決策後,他打算上阿里雲買MQ服務。我當時給他開了個玩笑:您這價錢把我請回來,並且公司還有運維,其實徹底能夠本身維護,要不我來負責,你把這每月的MQ費用給我加工資得了。當我下樓買了支維他檸檬茶後,他決定由咱們本身搭建RabbitMQ。這個決定跟個人想法差很少,緣由主要兩點:運維起來方便,吞吐沒有特別高。github
若是下文有總結不到位的,或者差錯的,能夠在下方評論反饋給我web
RabbitMQ模型Exchange在聲明時會綁定Queue和Binding Key,當Exchange收到消息會根據消息的sql
Routing Key與Exchange Type、Binding Key進行匹配,最後會路由到相關的隊列當中。Fanout,將消息發送到與該交換器所綁定的全部隊列中,與Routing Key、Bind Key無關,這就是廣播模式。Topic,經過對消息的Routing Key和Exchange、Queue進行匹配,將消息路由給一個或多個隊列,以此來達到發佈/訂閱模式。Direct,把消息路由到哪些Bind Key和Routing Key徹底匹配的隊列中。Headers,不依賴與路由鍵的匹配規則,基本用不上。docker
消費者會直接訂閱Queue裏的消息進行消費,多個消費者訂閱同個Queue會造成消息競爭狀態,以此達到負載均衡做用。vim
Kafka與RabbitMQ比沒有Exchange的概念,生產者直接發消息Topic(隊列)。瀏覽器
Kafka的訂閱者是經過消費組(Consumer Group)來體現的,每一個消費組均可以重複消費Topic一份完整的消息,不一樣消費組之間消費進度彼此不受影響。例如Message1能被Consumer Group 1和Consumer Group2裏的消費者都消費一次。緩存
消費組中包含多個消費者,同個Group的消費者之間是競爭消費的關係。例如Message2只可以被Consumer Group裏某一個Consumer只消費一次。安全
Kafka具備消息存儲的功能,消息被消費後不會被當即刪除,由於須要被不一樣的Consumer Group屢次消費同個消息,所以會在Topic維護一個Consumer Offset,每消費成功Offset自增1.
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.commi true,無論執行結果如何,消費者會自動提交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 --reloadKafka服務部署
下載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 --reloadKafka-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