手把手教你搭建高可用 RocketMQ 集羣!

_來源:jack_xu | https://juejin.cn/post/6929500274457313293
_

RocketMQ 發展歷史

RocketMQ 是一個由阿里巴巴開源的消息中間件,
2012 年開源,2017 年成爲 apache 頂級項目。RocketMQ 在阿里內部應用是非常廣泛的,阿里內部的幾千個應用都運行在 RocketMQ 之上,雙十一期間需要處理億萬級別的消息,TPS 可以達到幾十萬。目前支持 Java、C/C++,Python、Go 四種語言訪問。

RocketMQ 現在有兩個版本,一個是社區開源版,一個是商業的雲服務版(AliwareMQ)。最新版本:4.8.0(本文演示版本)。

它的核心設計借鑑了 Kafka,所以我們在學習 RocketMQ 的時候,會發現很多和 kafka 相同的特性,但是在某些功能上和 kafka 又有較大的差異,它有以下一些特性:

  1. 支持集羣模型、負載均衡、水平擴展能力

  2. 億級別消息堆積能力

  3. 採用零拷貝的原理,順序寫盤,隨機讀

  4. 底層通信框架採用 Netty NIO

  5. NameServer 代替 Zookeeper,實現服務尋址和服務協調

  6. 消息失敗重試機制、消息可查詢

  7. 強調集羣無單點,可擴展,任意一點高可用,水平可擴展

  8. 經過多次雙十一的考驗

高可用架構

RocketMQ 天生對集羣的支持非常好,它有以下一些模式:

(1)單 Master

優點:除了配置簡單沒什麼優點

缺點:不可靠,該機器重啓或者宕機,將要導致整個服務不可用

(2)多 Master

優點:配置簡單,性能最高

缺點:可能會有少量消息丟失(配置相關),單臺機器重啓或宕機期間,該機器下未被消費的消息在機器恢復前不可訂閱,影響消息實時性

(3)多 Master 多 Slave,每個 Master 配一個 Slave,有多對 Master-Slave,集羣採用異步複製方式,主備有短暫消息延遲,毫秒級

優點:性能同多 Master 幾乎一樣,實時性高,主備間切換對應用透明,不需人工干預

缺點:Master 宕機或磁盤損壞時會有少量消息丟失

(4)多 Master 多 Slave,每個 Master 配一個 Slave,有多對 Master-Slave,集羣採用同步雙寫方式,主備都寫成功,嚮應用返回成功

優點:服務可用性與數據可用性非常高

缺點:性能比異步集羣略低,當前版本主宕備不能自動切換爲主

本文采用的是二主二從安裝模式,即第四種多Master多Slave

二主二從異步集羣安裝

端口規劃

首先我買了兩臺雲服務器,平時我會用來學習安裝一些中間件,比較方便,大家有條件的話也可以買下,當然也可以通過在本地安裝虛擬機的方式來操作。

接下來我要通過這兩臺服務器來實現二主二從的安裝,首先對它們的端口進行一下規劃

    第一臺機器  42.192.77.73
    端口規劃:
    9876     NameServer1
    10910    BrokerA-master
    10921    BrokerB-slave

    第二臺機器  39.103.144.86
    端口規劃:
    9876     NameServer2
    10920    BrokerB-master
    10911    BrokerA-slave
    複製代碼

畫圖看上去更加清晰明瞭一些

下載

從官網  rocketmq.apache.org/  進去獲得最新的下載地址,紅框裏標註出來的

這裏的地址都可以,下載下來

    cd /jackxu
    wget https://mirror.bit.edu.cn/apache/rocketmq/4.8.0/rocketmq-all-4.8.0-bin-release.zip

下載好後解壓,改個名字

    unzip rocketmq-all-4.8.0-bin-release.zip
    mv unzip rocketmq-all-4.8.0-bin-release.zip rocketmq

配置第一臺機器

在兩臺機器上都下載、解壓好。在 rocketmq/conf 目錄下,有三種建議配置模式:

2m-2s-async(2 主 2 從異步) —— 本文采用這種

2m-2s-sync (2 主 2 從同步)

2m-noslave (2 主)

現在需要修改兩臺機器上 2m-2s-async 這個目錄中的文件。在 42.192.77.73 機器上修改 broker-a.properties

    cd /jackxu/rocketmq/conf/2m-2s-async
    vim  broker-a.properties

修改集羣名字

    brokerClusterName=jackxu-cluster

增加的內容

    #Broker 對外服務的監聽端口
    listenPort=10910
    #是否允許 Broker 自動創建Topic,建議線下開啓,線上關閉
    autoCreateTopicEnable=true
    #是否允許 Broker 自動創建訂閱組,建議線下開啓,線上關閉
    autoCreateSubscriptionGroup=true
    #nameServer地址,分號分割
    namesrvAddr=39.103.144.86:9876;42.192.77.73:9876
    #存儲路徑
    storePathRootDir=/jackxu/rocketmq/store/broker-a
    #commitLog 存儲路徑
    storePathCommitLog=/jackxu/rocketmq/store/broker-a/commitlog
    #消費隊列存儲路徑存儲路徑
    storePathConsumeQueue=/jackxu/rocketmq/store/broker-a/consumequeue
    #消息索引存儲路徑
    storePathIndex=/jackxu/rocketmq/store/broker-a/index
    #checkpoint 文件存儲路徑
    storeCheckpoint=/jackxu/rocketmq/store/checkpoint
    #abort 文件存儲路徑
    abortFile=/jackxu/rocketmq/store/abort

修改 broker-b-s.properties

    vim  broker-b-s.properties

修改集羣名字

    brokerClusterName=jackxu-cluster

增加的內容

    #Broker 對外服務的監聽端口
    listenPort=10921
    #是否允許 Broker 自動創建Topic,建議線下開啓,線上關閉
    autoCreateTopicEnable=true
    #是否允許 Broker 自動創建訂閱組,建議線下開啓,線上關閉
    autoCreateSubscriptionGroup=true
    #nameServer地址,分號分割
    namesrvAddr=39.103.144.86:9876;42.192.77.73:9876
    #存儲路徑
    storePathRootDir=/jackxu/rocketmq/store/broker-b-s
    #commitLog 存儲路徑
    storePathCommitLog=/jackxu/rocketmq/store/broker-b-s/commitlog
    #消費隊列存儲路徑存儲路徑
    storePathConsumeQueue=/jackxu/rocketmq/store/broker-b-s/consumequeue
    #消息索引存儲路徑
    storePathIndex=/jackxu/rocketmq/store/broker-b-s/index
    #checkpoint 文件存儲路徑
    storeCheckpoint=/jackxu/rocketmq/store/checkpoint
    #abort 文件存儲路徑
    abortFile=/jackxu/rocketmq/store/abort

配置第二臺機器

在 39.103.144.86 機器上修改 broker-b.properties

    cd /jackxu/rocketmq/conf/2m-2s-async
    vim  broker-b.properties

修改集羣名字

    brokerClusterName=jackxu-cluster

增加的內容

    #Broker 對外服務的監聽端口
    listenPort=10920
    #是否允許 Broker 自動創建Topic,建議線下開啓,線上關閉
    autoCreateTopicEnable=true
    #是否允許 Broker 自動創建訂閱組,建議線下開啓,線上關閉
    autoCreateSubscriptionGroup=true
    #nameServer地址,分號分割
    namesrvAddr=39.103.144.86:9876;42.192.77.73:9876
    #存儲路徑
    storePathRootDir=/jackxu/rocketmq/store/broker-b
    #commitLog 存儲路徑
    storePathCommitLog=/jackxu/rocketmq/store/broker-b/commitlog
    #消費隊列存儲路徑存儲路徑
    storePathConsumeQueue=/jackxu/rocketmq/store/broker-b/consumequeue
    #消息索引存儲路徑
    storePathIndex=/jackxu/rocketmq/store/broker-b/index
    #checkpoint 文件存儲路徑
    storeCheckpoint=/jackxu/rocketmq/store/checkpoint
    #abort 文件存儲路徑
    abortFile=/jackxu/rocketmq/store/abort

修改 broker-a-s.properties

    vim  broker-a-s.properties

修改集羣名字

    brokerClusterName=jackxu-cluster

增加的內容

    #Broker 對外服務的監聽端口
    listenPort=10911
    #是否允許 Broker 自動創建Topic,建議線下開啓,線上關閉
    autoCreateTopicEnable=true
    #是否允許 Broker 自動創建訂閱組,建議線下開啓,線上關閉
    autoCreateSubscriptionGroup=true
    #nameServer地址,分號分割
    namesrvAddr=39.103.144.86:9876;42.192.77.73:9876
    #存儲路徑
    storePathRootDir=/jackxu/rocketmq/store/broker-a-s
    #commitLog 存儲路徑
    storePathCommitLog=/jackxu/rocketmq/store/broker-a-s/commitlog
    #消費隊列存儲路徑存儲路徑
    storePathConsumeQueue=/jackxu/rocketmq/store/broker-a-s/consumequeue
    #消息索引存儲路徑
    storePathIndex=/jackxu/rocketmq/store/broker-a-s/index
    #checkpoint 文件存儲路徑
    storeCheckpoint=/jackxu/rocketmq/store/checkpoint
    #abort 文件存儲路徑
    abortFile=/jackxu/rocketmq/store/abort

創建數據目錄

第一臺機器 42.192.77.73 執行,只需要執行一次

    mkdir -p /jackxu/rocketmq/store/broker-a /jackxu/rocketmq/store/broker-a/consumequeue /jackxu/rocketmq/store/broker-a/commitlog /jackxu/rocketmq/store/broker-a/index /jackxu/rocketmq/logs /jackxu/rocketmq/store/broker-b-s /jackxu/rocketmq/store/broker-b-s/consumequeue /jackxu/rocketmq/store/broker-b-s/commitlog /jackxu/rocketmq/store/broker-b-s/index

第二臺機器 39.103.144.86 執行,只需要執行一次

    mkdir -p /jackxu/rocketmq/store/broker-a-s /jackxu/rocketmq/store/broker-a-s/consumequeue /jackxu/rocketmq/store/broker-a-s/commitlog /jackxu/rocketmq/store/broker-a-s/index /jackxu/rocketmq/logs /jackxu/rocketmq/store/broker-b /jackxu/rocketmq/store/broker-b/consumequeue /jackxu/rocketmq/store/broker-b/commitlog /jackxu/rocketmq/store/broker-b/index

啓動兩個 NameServer

在兩臺機器分別執行,& 表示在後臺運行,默認情況下,nameserver 監聽的是 9876 端口

    nohup sh /jackxu/rocketmq/bin/mqnamesrv >/jackxu/rocketmq/logs/mqnamesrv.log 2>&&

查看日誌

    tail -f /jackxu/rocketmq/logs/mqnamesrv.log

啓動 Broker

啓動的時候按照下面的順序來,-c 是指定 broker 的配置文件

1、啓動 73 的 A 主

    nohup sh /jackxu/rocketmq/bin/mqbroker -c /jackxu/rocketmq/conf/2m-2s-async/broker-a.properties > /jackxu/rocketmq/logs/broker-a.log 2>&&

2、啓動 86 的 A 從

    nohup sh /jackxu/rocketmq/bin/mqbroker -c /jackxu/rocketmq/conf/2m-2s-async/broker-a-s.properties > /jackxu/rocketmq/logs/broker-a-s.log 2>&&

3、啓動 86 的 B 主

    nohup sh /jackxu/rocketmq/bin/mqbroker -c /jackxu/rocketmq/conf/2m-2s-async/broker-b.properties > /jackxu/rocketmq/logs/broker-b.log 2>&&

4、啓動 73 的 B 從

    nohup sh /jackxu/rocketmq/bin/mqbroker -c /jackxu/rocketmq/conf/2m-2s-async/broker-b-s.properties > /jackxu/rocketmq/logs/broker-b-s.log 2>&&

查看日誌

    tail -f /jackxu/rocketmq/conf/2m-2s-async/broker-a.properties
    tail -f /jackxu/rocketmq/conf/2m-2s-async/broker-a-s.properties
    tail -f /jackxu/rocketmq/conf/2m-2s-async/broker-b.properties
    tail -f /jackxu/rocketmq/conf/2m-2s-async/broker-b-s.properties

檢查是否啓動成功

輸入 jps 命令,一共四個進程沒問題

但是大多數情況下不會這麼順利,我在安裝中有一些坑點:

1、沒有安裝 jdk,因爲這是我新的服務器,上面是沒有 jdk 環境的,大家知道 rocketmq 是用 java 寫的,所以需要有 java 環境才能運行,包括 jps 命令就是查看 java 進程

2、內存不足,因爲默認的配置文件設置了很大的內存,但是我的機器只有 1 核 2G,肯定是不夠的,所以在啓動的時候會報內存不足

解決辦法就是修改配置文件

    vim /jackxu/rocketmq/bin/runserver.sh
    vim /jackxu/rocketmq/bin/runbroker.sh

把 NameServer 和 Broker 的內存大小都改小一點,然後重新啓動即可

關閉命令

停止服務的時候需要注意,要先停止 broker,其次停止 nameserver。

    cd /jackxu/rocketmq/bin

    sh mqshutdown namesrv
    sh mqshutdown broker
    複製代碼

web 控制檯安裝

與 kafka 不同的是,rocket 官方提供了一個可視化控制檯,大家可以在這裏下載

https://github.com/apache/rocketmq-externals

這個是 rocketmq 的擴展,裏面不僅包含控制檯的擴展,也包含對大數據 flume、hbase 等組件的對接和擴展。

下載

下載源碼,一般下載速度會比較慢,等不及的話可以去網盤下載鏈接:

https://pan.baidu.com/s/1-eg5JK8Te9uVAwADZeO_Dw
提取碼:jack

    cd /jackxu
    wget https://github.com/apache/rocketmq-externals/archive/master.zip

解壓

    unzip master.zip

修改配置文件

    cd /jackxu/rocketmq-externals-master/rocketmq-console/src/main/resources
    vim application.properties

這是一個 spring boot 項目,我們需要修改裏面的參數

    //修改端口號:
    server.port=7298
    //修改name server地址(多個地址用英文分號隔開)
    rocketmq.config.namesrvAddr=39.103.144.86:9876;42.192.77.73:9876

打包

打成一個 jar 包, 這裏需要先安裝maven,編譯慢的話可以替換成淘寶的鏡像

    cd /jackxu/rocketmq-externals-master/rocketmq-console
    mvn clean package -Dmaven.test.skip=true

啓動 jar 包

    cd target
    java -jar rocketmq-console-ng-2.0.0.jar

訪問

訪問一下  http://42.192.77.73:7298/  ,可以看到都已經啓動成功了

踩坑點

這裏有兩個踩坑點,在啓動的時候會報錯

(1)spring
boot 啓動的時候報連接不上 39.103.144.86:9876;42.192.77.73:9876,這裏我的第一反應是防火牆的原因,關閉一下

    systemctl disable firewalld.service

再次啓動還是不行,然後我的第二個反應是端口沒有開放,telnet 一下

    telnet 42.192.77.73 9876

果然 telnet 不通,原因是這樣的,我安裝在雲服務器上,默認端口是不開放的,需要到控制檯打開,這也算是一個經驗吧。

(2)再次啓動的時候又報了另一個錯誤,連接不上 172.26.182.88:9876,當時我就奇怪了,我寫的地址裏沒有這個地址啊,怎麼在連接它,而且這個 IP 看上去又像是內網地址,後來我打開阿里雲控制檯一看,果真是這臺機器的內網地址,然後我又百度了一番,大概原因就是 RocketMQ 是阿里開源的,而那臺機器又是阿里雲的機器,它的源碼裏應該是優先連接到阿里雲的內網地址,網上的做法是在配置文件裏面顯式的加上公網地址即可解決。

    #新增公網IP
    brokerIP1=39.103.144.86

控制檯介紹

其中最常用的是集羣,主題,消費者和消息這四部分。

配置文件說明

下面介紹一下安裝 RocketMQ 配置文件裏面的屬性首先是集羣名字相同,上面四臺機器的集羣名字都叫 brokerClusterName=jackxu-cluster,其次是連接到相同的 NameServer,namesrvAddr=39.103.144.86:9876;42.192.77.73:9876。在配置文件中 brokerId=0 代表 master,brokerId=1 代表 slave。

在配置文件中還有這兩個屬性

brokerRole 在 master broker 可以配置成 SYNC_MASTER 或者 ASYNC_MASTER,在 slave broker 統一配置成 SLAVE

H6kan7

flushDiskType 分爲 ASYNC_FLUSH 和 SYNC_FLUSH

7wF6Fp

流程圖

我們推薦的配置是異步刷盤 + 同步複製。

HA 與故障轉移

在之前的版本中,RocketMQ 只有 master/slave 一種部署方式,一組 broker 中有一個 master,有 0 到多個 slave,這種模式下提供了一定的高可用性。

master 在掛了的情況下,slave 仍然可以提供讀服務。默認情況下,讀寫都在 master 上,如果開啓了 slaveReadEnable=true,slave 也可以參與讀負載,但是是在 master 積壓的消息超過了物理內存的 40%,纔會默認轉向 brokerId 爲 1 的從服務器讀取,具體轉向哪臺機器由 whichBrokerWhenConsumeSlowly 參數控制。

    org.apache.rocketmq.common.subscription.SubscriptionGroupConfig
private long whichBrokerWhenConsumeSlowly=1;

由於是多主的存在,當一個 master 掛了以後,可以寫到其他的 master 上。

RocketMQ 2019 年 3 月發佈的 4.5.0 版本中,利用 Dledger 技術解決了自動選主的問題。Dledger 就是一個基於 raft 協議的 commitlog 存儲庫,也是 RocketMQ 實現新的高可用多副本架構的關鍵。它的優點是不需要引入外部組件,自動選主邏輯集成到各個節點的進程中,節點之間通過通信就可以完成選主。

架構圖

在這種情況下,commitlog 是 Dledger 管理的,具有選主的功能。默認是不開啓,如果需要開啓,需要在配置文件裏面添加以下配置:

    # 是否啓用DLedger
    enableDLegerCommitLog=true
    # DLedger Raft Group的名字
    dLegerGroup=broker-a
    # DLedger Group內各節點的地址和端口,至少需要3個節點
    dLegerPeers=n0-192.168.44.163:10911;n1-192.168.44.164:10911;n2-192.168.44.165:10911
    # 本節點id
    dLegerSelfId=n0

結語

小夥伴在學習一箇中間件的時候一定要動手實踐安裝,首先是體驗一下安裝的過程氛圍,瞭解一些參數配置,在公司裏這個操作一般是由運維來完成的,雖然我們平時接觸不到,但是學習還是需要的,不一定需要精,至少是要會;其次是爲後面的寫代碼做實驗做準備,發消息消費消息總得有個地方吧,這也是 RocketMQ 的第一篇,後面我還會介紹其使用方法及原理,大家敬請期待…

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。