主從自動故障轉移模式
本文檔主要介紹如何部署支援自動主從切換的 RocketMQ 叢集。其架構如上圖所示。它主要新增支援自動主從切換的控制器元件,可以獨立部署或嵌入 NameServer 中。
控制器部署
控制器組件提供主控的選擇。如果控制器需要容錯,則需要部署在三個或更多副本中(遵循 Raft 多數協議)。
如果控制器僅部署為單副本,則仍可完成 Broker 故障轉移,但如果單點控制器發生故障,將影響切換能力,但不影響現有集群的正常收發。
部署控制器有兩種方式,一種是嵌入在 NameServer 中部署,通過設置 enableControllerInNamesrv(可以選擇性開啟,不需要每個 NameServer 都開啟)開啟。這種模式下,NameServer 自身仍然是無狀態的,即嵌入模式下 NameServer 發生故障,只會影響切換能力,不影響原有的路由獲取等功能。另一種是獨立部署控制器組件。
嵌入控制器在 NameServer 中部署
當控制器嵌入在 NameServer 中部署時,只需要在 NameServer 的配置文件中設置enableControllerInNamesrv=true
,並填寫控制器配置即可。
enableControllerInNamesrv = true
controllerDLegerGroup = group1
controllerDLegerPeers = n0-127.0.0.1:9877;n1-127.0.0.1:9878;n2-127.0.0.1:9879
controllerDLegerSelfId = n0
controllerStorePath = /home/admin/DledgerController
enableElectUncleanMaster = false
notifyBrokerRoleChanged = true
參數說明:
- enableControllerInNamesrv:是否啟用 Nameserver 中的控制器,默認為 false。
- controllerDLegerGroup:DLedger Raft 組的名稱,在同一個 DLedger Raft 組內必須保持一致。
- controllerDLegerPeers:DLedger 組內節點的端口信息,同一個組內節點的配置必須保持一致。
- controllerDLegerSelfId:節點 id,必須是 controllerDLegerPeers 中的一個;同一個組內每個節點必須唯一。
- controllerStorePath:控制器日誌存儲位置。控制器是有狀態的,控制器需要依賴日誌在重啟或崩潰後恢復數據。這個目錄非常重要,不能隨意刪除。
- enableElectUncleanMaster:是否允許從 SyncStateSet 外部選舉 Master。如果為 true,可能會選擇一個數據過期的副本作為 master,導致消息丟失。默認為 false。
- notifyBrokerRoleChanged:是否主動通知 Broker 副本組角色變更,預設為 true。
設定完參數後,即可指定設定檔啟動 Nameserver。
$ nohup sh bin/mqnamesrv -c namesrv.conf &
Controller 獨立部署
獨立部署,執行以下腳本
$ nohup sh bin/mqcontroller -c controller.conf &
mqcontroller 腳本位於原始碼套件的 distribution/bin/mqcontroller
,設定參數與內嵌模式相同。
Controller 獨立部署後,仍需另外部署 NameServer,提供路由發現能力。
Broker 部署
Broker 啟動方式與之前相同,新增以下參數
- enableControllerMode:Broker controller 模式的總開關,只有此值為 true 時,才會啟用自動主從切換模式,預設為 false。
- controllerAddr:controller 的地址,多個 controller 間以分號隔開,例如:
controllerAddr = 127.0.0.1:9877;127.0.0.1:9878;127.0.0.1:9879
- syncBrokerMetadataPeriod:同步 Broker 副本資訊到 controller 的時間間隔,預設為 5000(5s)。
- checkSyncStateSetPeriod:檢查 SyncStateSet 的時間間隔,檢查 SyncStateSet 可能會縮減 SyncState,預設為 5000(5s)。
- syncControllerMetadataPeriod:同步 controller metadata 的時間間隔,主要是取得 active controller 的地址,預設為 10000(10s)。
- haMaxTimeSlaveNotCatchup:Slave 未追上 Master 的最大時間間隔,若 SyncStateSet 中的 slave 超過此時間間隔,將會被移除 SyncStateSet,預設為 15000(15s)。
- storePathEpochFile:epoch 檔案存放位置,epoch 檔案非常重要,不可隨意刪除,預設為 store 目錄下。
- allAckInSyncStateSet:如果此值為 true,則只有當訊息已複製到 SyncStateSet 中的每個副本時,才會將訊息傳回給客戶端,確保訊息不會遺失。預設值為 false。
- syncFromLastFile:如果從屬伺服器是空白磁碟啟動,是否從最後一個檔案複製。預設值為 false。
- asyncLearner:如果此值為 true,副本將不會進入 SyncStateSet,也就是說,它不會被選為主控端,但會一直作為學習者副本並執行非同步複製。預設值為 false。
- inSyncReplicas:需要保持同步的副本組數,預設值為 1,且當 allAckInSyncStateSet=true 時,此參數無效。
- minInSyncReplicas:需要保持同步的副本組的最小數目。如果 SyncStateSet 中的副本數小於 minInSyncReplicas,putMessage 會傳回 PutMessageStatus.IN_SYNC_REPLICAS,預設值為 1
在控制器模式中,Broker 組態必須設定 enableControllerMode=true 並填入 controllerAddr,並使用以下指令啟動
$ nohup sh bin/mqbroker -c broker.conf &
在自動主從切換模式中,Broker 不需要指定 brokerId 和 brokerRole,這些會由控制器元件指派。
相容性
此模式不會對任何客戶端等級的 API 進行任何變更或修改,且與客戶端沒有相容性問題。
Nameserver 本身沒有被修改,且與 Nameserver 沒有相容性問題。如果啟用 enableControllerInNamesrv,且控制器參數正確組態,則會啟用控制器功能。
如果將 Broker 設定為 enableControllerMode=false
,它仍會像以前一樣運作。如果 enableControllerMode=true
,則必須部署控制器且參數必須正確組態才能正常運作。
具體行為顯示在以下表格中
舊 Nameserver | 舊 Nameserver + 獨立部署控制器 | 新 Nameserver 啟用控制器 | 新 Nameserver 停用控制器 | |
---|---|---|---|---|
舊 Broker | 正常執行,無法故障轉移 | 正常執行,無法故障轉移 | 正常執行,無法故障轉移 | 正常執行,無法故障轉移 |
新 Broker 啟用控制器模式 | 無法正常上線 | 正常執行,可以故障轉移 | 正常執行,可以故障轉移 | 無法正常上線 |
新 broker 禁用控制器模式 | 正常執行,無法故障轉移 | 正常執行,無法故障轉移 | 正常執行,無法故障轉移 | 正常執行,無法故障轉移 |
升級注意事項
從上述相容性聲明中可以看出,NameServer 可以正常升級且沒有相容性問題。在不升級 Nameserver 的情況下,可以獨立部署控制器組件以獲取切換能力。對於 broker 升級,有兩種情況
主從部署升級為控制器切換架構
可以進行資料就地升級。對於每一組 Brokers,停止主備用 Brokers,並確保主備用 CommitLogs 對齊(可以在升級前一段時間禁止寫入此組 Brokers,或透過複製確保一致性)。升級套件後,重新啟動。
注意如果主備用 CommitLogs 沒有對齊,則必須確保主機在備用機上線之前上線,否則可能會因資料截斷而導致訊息遺失。
從 DLedger 模式升級到控制器切換架構
由於 DLedger 模式和主從模式中訊息資料格式的差異,沒有資料就地升級。在部署多組 Brokers 的情況下,可以禁止寫入一組 Brokers 一段時間(只要確認所有現有訊息都已使用),然後升級並部署控制器和新的 Brokers。這樣,新的 Brokers 將從現有的 Brokers 使用訊息,而現有的 Brokers 將從新的 Brokers 使用訊息,直到使用量平衡,然後可以停用現有的 Brokers。