1. 程式人生 > >說說MQ之RocketMQ(一)

說說MQ之RocketMQ(一)

RocketMQ 是出自 A 公司的開源產品,用 Java 語言實現,在設計時參考了 Kafka,並做出了自己的一些改進,訊息可靠性上比 Kafka 更好,目前,RocketMQ 的文件仍然不夠豐富 1 2,社群仍然無法與 Kafka 比肩,但 A 公司已經推出了基於 RocketMQ 的雲產品 3,相信未來 RocketMQ 也會有不錯的發展。本文采用 RocketMQ 3.2.6 進行實驗,由於 RocketMQ 與 Kafka 很相似,本文很多地方對兩者做出了比較。

基本概念

RocketMQ 由於借鑑了 Kafka 的設計,包括元件的命名也很多與 Kafka 相似,下面摘抄一段《RocketMQ 原理簡介》中的介紹,可以與 Kafka 的命名比對一下,

  • Producer,訊息生產者,負責產生訊息,一般由業務系統負責產生訊息。
  • Consumer,訊息消費者,負責消費訊息,一般是後臺系統負責非同步消費。
  • Push Consumer,Consumer 的一種,應用通常向 Consumer 物件註冊一個 Listener 介面,一旦收到訊息,Consumer 物件立 刻回撥 Listener 介面方法。
  • Pull Consumer,Consumer 的一種,應用通常主動呼叫 Consumer 的拉訊息方法從 Broker 拉訊息,主動權由應用控制。
  • Producer Group,一類 Producer 的集合名稱,這類 Producer 通常傳送一類訊息,且傳送邏輯一致。
  • Consumer Group,一類 Consumer 的集合名稱,這類 Consumer 通常消費一類訊息,且消費邏輯一致。
  • Broker,訊息中轉角色,負責儲存訊息,轉發訊息,一般也稱為 Server。在 JMS 規範中稱為 Provider。

《RocketMQ 原理簡介》中還介紹了一些其他的概念,例如,廣播消費和叢集消費,廣播消費是 Consumer Group 中對於同一條訊息每個 Consumer 都消費,叢集消費是 Consumer Group 中對於同一條訊息只有一個 Consumer 消費。Kafka 採用的是叢集消費,不支援廣播消費(好吧,是我沒有找到)。再例如,普通順序訊息和嚴格順序訊息,普通順序訊息在 Broker 重啟情況下不會保證訊息順序性;嚴格順序訊息即使在異常情況下也會保證訊息的順序性。個人理解,所謂普通順序訊息,應該就是 Kafka 中的 Partition 級別有序,嚴格順序訊息,應該是 Topic 級別有序,但文中也提到,這樣的有序級別是要付出代價的,Broker 叢集中只要有一臺機器不可用,則整個叢集都不可用,降低服務可用性。使用這種模式,需要依賴同步雙寫,主備自動切換,但自動切換功能目前還未實現(我猜,自動切換僅僅是沒開源吧)。說白了,嚴格順序訊息不具備生產可用性,自己玩玩還行,其應用場景主要是資料庫 binlog 同步。

關於 RocketMQ 和 Kafka 的對比,可以參考 RocketMQ Wiki 中的文章 4,看看就行,不必較真。

關於順序和分割槽

順序性的話題,剛才已經提到了一些,RocketMQ 的實現應該不弱於 Kafka。對於分割槽,RocketMQ 似乎有意弱化了這個概念,只有在 Producer 中有一個引數 defaultTopicQueueNums,分割槽在 RocketMQ 中有時被稱為佇列。RocketMQ 的普通順序訊息模式,應該就是分割槽順序性,這點與 Kafka 一致。

關於高可用

RocketMQ 實現高可用的方式有多種,《RocketMQ 使用者指南》文件中提到的有:多主模式、多主多從非同步複製模式、多主多從同步複製模式。多主模式下,效能較好,但是在 Broker 宕機的時候,該 Broker 上未消費的交易不可消費;多主多從非同步複製模式,與 Kafka 的副本模式比較類似,主 Broker 宕機後,會自動切換到從 Broker,訊息的消費不會出現間斷;多主多從同步複製模式更進一步,採用同步刷盤的方式,避免了主 Broker 宕機帶來的訊息丟失,但是,目前不支援自動切換。

雖然 RocketMQ 提供了多種高可用方式,但是目前能生產使用的就只有多主多從非同步複製模式,即使在這個模式上,其實現也比 Kafka 要差。因為 RocketMQ 的機制中,主從關係是人為指定的,主 Broker 上承擔所有的訊息派發,而 Kafka 的主從關係是通過選舉的方式選出來的,每個分割槽的主節點都是不一樣的,可以從不同的節點派發訊息。Kafka 的模式是分散模式,有利於負載均衡,而且當一個 Broker 宕機的時候,隻影響部分 Topic,而 RocketMQ 一旦主 Broker 宕機,會影響所有的 Topic。另外,Kafka 可以支援 Broker 間同步複製(通過設定 Broker 的 acks 引數),這樣比的話,RocketMQ 就差太多了。

關於 RocketMQ 的介紹,網上的文章不算太多,也比較雜,《分散式開放訊息系統(RocketMQ)的原理與實踐》5 6 7這篇原理介紹的不錯,推薦。

RocketMQ 的工具和程式設計介面

RocketMQ 的工具

相比較 Kafka 而言,RocketMQ 提供的工具要少一些,如下,

bin/mqadmin
bin/mqbroker
bin/mqbroker.numanode0
bin/mqbroker.numanode1
bin/mqbroker.numanode2
bin/mqbroker.numanode3
bin/mqfiltersrv
bin/mqnamesrv
bin/mqshutdown

除了程序啟停之外,常用的運維命令都在 mqadmin 中,詳見《RocketMQ 運維指令》文件。我實驗中常用的一些命令如下,

sh mqnamesrv &
sh mqbroker -c async-broker-a.properties &
sh mqbroker -c async-broker-a-s.properties &
sh mqadmin topicList -n 192.168.232.23:9876
sh mqadmin topicRoute -n 192.168.232.23:9876 -t TopicTestjjj
sh mqadmin clusterList -n 192.168.232.23:9876
sh mqadmin deleteTopic -c DefaultCluster -n 192.168.232.23:9876 -t TopicTestjjj
sh mqadmin consumerProgress -n 192.168.232.23:9876 -g ConsumerGroupNamecc4
sh mqadmin deleteSubGroup -c DefaultCluster -n 192.168.232.23:9876 -g ConsumerGroupNamecc4
sh mqadmin consumerConnection -n 192.168.232.23:9876 -g ConsumerGroupNamecc4

RocketMQ 使用了自己的 name server 來做排程(Kafka 用了 Zookeeper),使用 sh mqnamesrv 來啟動,預設監聽埠9876,sh mqnamesrv -m 可以檢視所有預設引數,使用 -c xxxx.properties 引數來指定自定義配置。sh mqbroker 是用於啟動 Broker 的命令,引數比較多,詳細可以通過 sh mqbroker -m 檢視預設引數,配置項細節後文再說。sh mqadmin 是運維命令入口,topicList 是列出所有 Topic;topicRoute 是列出單個 Topic 的詳細資訊;clusterList 是列出叢集的資訊;deleteTopic 是刪除 Topic。consumerProgress 是檢視消費者消費進度,deleteSubGroup 是刪除消費者的訂閱,consumerConnection 是查詢消費者訂閱的情況。

Broker 的配置是最多的,實驗中我修改到的部分如下,其他使用預設,

brokerClusterName=DefaultCluster
brokerIP1=192.168.232.23
brokerName=broker-a
brokerId=0
namesrvAddr=192.168.232.23:9876
listenPort=10911
deleteWhen=04
fileReservedTime=120
storePathRootDir=/home/arnes/alibaba-rocketmq/data/store-a-async
storePathCommitLog=/home/arnes/alibaba-rocketmq/data/store-a-async/commitlog
brokerRole=ASYNC_MASTER
flushDiskType=ASYNC_FLUSH

配置檔案中的多數配置看例子就可以知道意思,挑幾個說一下。brokerName 和 brokerId, 同名的 Broker,ID 是0的是主節點,其他是從節點;deleteWhen,刪除檔案時間點,預設凌晨4點;fileReservedTime,檔案保留時間,設定為120小時;brokerRole,Broker 的角色,ASYNC_MASTER 是非同步複製主節點,SYNC_MASTER 是同步雙寫主節點,SLAVE 是備節點。

其實,這些工具的寫法也基本一致,都是先做一些檢查,最後執行 Java 程式,JVM 系統上的應用應該差不多都這樣。