天天看點

同程旅行基于 RocketMQ 高可用架構實踐背景介紹MQ 雙中心改造MQ 平台治理

同程旅行基于 RocketMQ 高可用架構實踐背景介紹MQ 雙中心改造MQ 平台治理

背景介紹

為何選擇 RocketMQ

我們在幾年前決定引入 MQ 時,市場上已經有不少成熟的解決方案,比如 RabbitMQ , ActiveMQ,NSQ,Kafka 等。考慮到穩定性、維護成本、公司技術棧等因素,我們選擇了 RocketMQ :

  • 純 Java 開發,無依賴,使用簡單,出現問題能 hold ;
  • 經過阿裡雙十一考驗,性能、穩定性可以保障;
  • 功能實用,發送端:同步、異步、單邊、延時發送;消費端:消息重置,重試隊列,死信隊列;
  • 社群活躍,出問題能及時溝通解決。

使用情況

  • 主要用于削峰、解耦、異步處理;
  • 已在火車票、機票、酒店等核心業務廣泛使用,扛住巨大的微信入口流量;
  • 在支付、訂單、出票、資料同步等核心流程廣泛使用;
  • 每天 1000+ 億條消息周轉。

下圖是 MQ 接入架構圖

由于公司技術棧原因,client sdk 我們提供了 java sdk ;對于其他語言,收斂到 http proxy ,屏蔽語言細節,節約維護成本。按照各大業務線,對後端存儲節點進行了隔離,互相不影響。

同程旅行基于 RocketMQ 高可用架構實踐背景介紹MQ 雙中心改造MQ 平台治理

MQ 雙中心改造

之前單機房出現過網絡故障,對業務影響較大。為保障業務高可用,同城雙中心改造提上了日程。

為何做雙中心

  • 單機房故障業務可用;​
  • 保證資料可靠:若所有資料都在一個機房,一旦機房故障,資料有丢失風險;
  • 橫向擴容:單機房容量有限,多機房可分擔流量。

雙中心方案

做雙中心之前,對同城雙中心方案作了些調研,主要有冷(熱)備份、雙活兩種。(當時社群 Dledger 版本還沒出現,Dledger 版本完全可做為雙中心的一種可選方案。)

1)同城冷(熱)備份

兩個獨立的 MQ 叢集, 使用者流量寫到一個主叢集,資料實時同步到備用叢集,社群有成熟的 RocketMQ Replicator 方案,需要定期同步中繼資料,比如主題,消費組,消費進度等。

同程旅行基于 RocketMQ 高可用架構實踐背景介紹MQ 雙中心改造MQ 平台治理

2)同城雙活

兩個獨立 MQ 叢集,使用者流量寫到各自機房的 MQ 叢集,資料互相不同步。

平時業務寫入各自機房的 MQ 叢集,若一個機房挂了,可以将使用者請求流量全部切到另一個機房,消息也會生産到另一個機房。

同程旅行基于 RocketMQ 高可用架構實踐背景介紹MQ 雙中心改造MQ 平台治理

對于雙活方案,需要解決 MQ 叢集域名。

1)若兩個叢集用一個域名,域名可以動态解析到各自機房。此方式要求生産、消費必須在同一個機房。假如生産在 idc1 ,消費在 idc2 ,這樣生産、消費各自連接配接一個叢集,沒法消費資料。

2)若一個叢集一個域名,業務方改動較大,我們之前對外服務的叢集是單中心部署的,業務方已經大量接入,此方案推廣較困難。

為盡可能減少業務方改動,域名隻能繼續使用之前的域名,最終我們采用一個 Global MQ 叢集,跨雙機房,無論業務是單中心部署還是雙中心部署都不影響;而且隻要更新用戶端即可,無需改動任何代碼。

雙中心訴求

  • 就近原則:生産者在 A 機房,生産的消息存于 A 機房 broker ; 消費者在 A 機房,消費的消息來自 A 機房 broker 。
  • 單機房故障:生産正常,消息不丢。
  • broker 主節點故障:自動選主。

就近原則

簡單說,就是确定兩件事:

  • 節點(用戶端節點,服務端節點)如何判斷自己在哪個 idc;
  • 用戶端節點如何判斷服務端節點在哪個 idc。

如何判斷自己在哪個 idc?

1) ip 查詢

節點啟動時可以擷取自身 ip ,通過公司内部的元件查詢所在的機房。

2)環境感覺

需要與運維同學一起配合,在節點裝機時,将自身的一些中繼資料,比如機房資訊等寫入本地配置檔案,啟動時直接讀寫配置檔案即可。

我們采用了第二個方案,無元件依賴,配置檔案中 logicIdcUK 的值為機房标志。

同程旅行基于 RocketMQ 高可用架構實踐背景介紹MQ 雙中心改造MQ 平台治理

用戶端節點如何識别在同一個機房的服務端節點?

用戶端節點可以拿到服務端節點的 ip 以及 broker 名稱的,是以:

  • ip 查詢:通過公司内部元件查詢 ip 所在機房資訊;
  • broker 名稱增加機房資訊:在配置檔案中,将機房資訊添加到 broker 名稱上;
  • 協定層增加機房辨別:服務端節點向中繼資料系統注冊時,将自身的機房資訊一起注冊。

相對于前兩者,實作起來略複雜,改動了協定層, 我們采用了第二種與第三種結合的方式。

就近生産

基于上述分析,就近生産思路很清晰,預設優先本機房就近生産;

若本機房的服務節點不可用,可以嘗試擴機房生産,業務可以根據實際需要具體配置。

同程旅行基于 RocketMQ 高可用架構實踐背景介紹MQ 雙中心改造MQ 平台治理

就近消費

優先本機房消費,預設情況下又要保證所有消息能被消費。

隊列配置設定算法采用按機房配置設定隊列

  • 每個機房消息平均分給此機房消費端;
  • 此機房沒消費端,平分給其他機房消費端。

僞代碼如下:

Map<String, Set> mqs = classifyMQByIdc(mqAll);
Map<String, Set> cids = classifyCidByIdc(cidAll);
Set<> result = new HashSet<>;
for(element in mqs){
                     result.add(allocateMQAveragely(element, cids, cid)); //cid為目前用戶端
}           

消費場景主要是消費端單邊部署與雙邊部署。

單邊部署時,消費端預設會拉取每個機房的所有消息。

同程旅行基于 RocketMQ 高可用架構實踐背景介紹MQ 雙中心改造MQ 平台治理

雙邊部署時,消費端隻會消費自己所在機房的消息,要注意每個機房的實際生産量與消費端的數量,防止出現某一個機房消費端過少。

同程旅行基于 RocketMQ 高可用架構實踐背景介紹MQ 雙中心改造MQ 平台治理

單機房故障

  • 每組 broker 配置

一主兩從,一主一從在一機房,一從在另一機房;某一從同步完消息,消息即發送成功。

消息生産跨機房;未消費消息在另一機房繼續被消費。

故障切主

在某一組 broker 主節點出現故障時,為保障整個叢集的可用性,需要在 slave 中選主并切換。要做到這一點,首先得有個broker 主故障的仲裁系統,即 nameserver(以下簡稱 ns )中繼資料系統(類似于 redis 中的哨兵)。

ns 中繼資料系統中的節點位于三個機房(有一個第三方的雲機房,在雲上部署 ns 節點,中繼資料量不大,延時可以接受),三個機房的 ns 節點通過 raft 協定選一個leader,broker 節點會将中繼資料同步給 leader, leader 在将中繼資料同步給 follower 。

用戶端節點擷取中繼資料時, 從 leader,follower 中均可讀取資料。

同程旅行基于 RocketMQ 高可用架構實踐背景介紹MQ 雙中心改造MQ 平台治理

切主流程

  • 若 nameserver leader 監控到 broker 主節點異常, 并要求其他 follower 确認;半數 follower 認為 broker 節點異常,則 leader 通知在 broker 從節點中選主,同步進度大的從節點選為主;
  • 新選舉的 broker 主節點執行切換動作并注冊到中繼資料系統;
  • 生産端無法向舊 broker 主節點發送消息。

流程圖如下

同程旅行基于 RocketMQ 高可用架構實踐背景介紹MQ 雙中心改造MQ 平台治理
同程旅行基于 RocketMQ 高可用架構實踐背景介紹MQ 雙中心改造MQ 平台治理

切中心演練

使用者請求負載到雙中心,下面的操作先将流量切到二中心---回歸雙中心---切到一中心。確定每個中心均可承擔全量使用者請求。

先将使用者流量全部切到二中心

同程旅行基于 RocketMQ 高可用架構實踐背景介紹MQ 雙中心改造MQ 平台治理
同程旅行基于 RocketMQ 高可用架構實踐背景介紹MQ 雙中心改造MQ 平台治理

流量回歸雙中心,并切到一中心

同程旅行基于 RocketMQ 高可用架構實踐背景介紹MQ 雙中心改造MQ 平台治理

回顧

  • 全局 Global 叢集
  • 一主二從,寫過半消息即及寫入成功
  • 中繼資料系統 raft 選主
  • broker 主節點故障,自動選主

MQ 平台治理

即使系統高性能、高可用,倘若随便使用或使用不規範,也會帶來各種各樣的問題,增加了不必要的維護成本,是以必要的治理手段不可或缺。

目的

​讓系統更穩定

  • 及時告警
  • 快速定位、止損

治理哪些方面

主題/消費組治理

  • 申請使用

生産環境 MQ 叢集,我們關閉了自動建立主題與消費組,使用前需要先申請并記錄主題與消費組的項目辨別與使用人。一旦出現問題,我們能夠立即找到主題與消費組的負責人,了解相關情況。若存在測試,灰階,生産等多套環境,可以一次申請多個叢集同時生效的方式,避免逐個叢集申請的麻煩。

  • 生産速度

為避免業務疏忽發送大量無用的消息,有必要在服務端對主題生産速度進行流控,避免這個主題擠占其他主題的處理資源。

  • 消息積壓

對消息堆積敏感的消費組,使用方可設定消息堆積數量的門檻值以及報警方式,超過這個門檻值,立即通知使用方;亦可設定消息堆積時間的門檻值,超過一段時間沒被消費,立即通知使用方。

  • 消費節點掉線

消費節點下線或一段時間無響應,需要通知給使用方。

用戶端治理

  • 發送、消費耗時檢測

監控發送/消費一條消息的耗時,檢測出性能過低的應用,通知使用方着手改造以提升性能;同時監控消息體大小,對消息體大小平均超過 10 KB 的項目,推動項目啟用壓縮或消息重構,将消息體控制在 10 KB 以内。

  • 消息鍊路追蹤

一條消息由哪個 ip 、在哪個時間點發送,又由哪些 ip 、在哪個時間點消費,再加上服務端統計的消息接收、消息推送的資訊,構成了一條簡單的消息鍊路追蹤,将消息的生命周期串聯起來,使用方可通過查詢msgId或事先設定的 key 檢視消息、排查問題。

  • 過低或有隐患版本檢測

随着功能的不斷疊代,sdk 版本也會更新并可能引入風險。定時上報 sdk 版本,推動使用方更新有問題或過低的版本。

服務端治理

  • 叢集健康巡檢

如何判斷一個叢集是健康的?定時檢測叢集中節點數量、叢集寫入 tps 、消費 tps ,并模拟使用者生産、消費消息。

  • 叢集性能巡檢

性能名額最終反映在處理消息生産與消費的時間上。服務端統計處理每個生産、消費請求的時間,一個統計周期内,若存在一定比例的消息處理時間過長,則認為這個節點性能有問題;引起性能問題的原因主要是系統實體瓶頸,比如磁盤 io util 使用率過高,cpu load 高等,這些硬體名額通過夜鷹監控系統自動報警。

  • 叢集高可用

高可用主要針對 broker 中 master 節點由于軟硬體故障無法正常工作,slave 節點自動被切換為 master ,适合消息順序、叢集完整性有要求的場景。

部分背景操作展示

主題與消費組申請

同程旅行基于 RocketMQ 高可用架構實踐背景介紹MQ 雙中心改造MQ 平台治理

生産,消費,堆積實時統計

同程旅行基于 RocketMQ 高可用架構實踐背景介紹MQ 雙中心改造MQ 平台治理

叢集監控

同程旅行基于 RocketMQ 高可用架構實踐背景介紹MQ 雙中心改造MQ 平台治理

踩過的坑

社群對 MQ 系統經曆了長時間的改進與沉澱,我們在使用過程中也到過一些問題,要求我們能從深入了解源碼,做到出現問題心不慌,快速止損。

  • 新老消費端并存時,我們實作的隊列配置設定算法不相容,做到相容即可;
  • 主題、消費組數量多,注冊耗時過長,記憶體 oom ,通過壓縮縮短注冊時間,社群已修複;
  • topic 長度判斷不一緻,導緻重新開機丢消息,社群已修複;
  • centos 6.6 版本中,broker 程序假死,更新 os 版本即可。

MQ 未來展望

目前消息保留時間較短,不友善對問題排查以及資料預測,我們接下來将對曆史消息進行歸檔以及基于此的資料預測。

  • 曆史資料歸檔
  • 底層存儲剝離,計算與存儲分離
  • 基于曆史資料,完成更多資料預測
  • 服務端更新到 Dledger ,確定消息的嚴格一緻

了解更多 RocketMQ 資訊,可加入社群交流群,下面是釘釘群,歡迎大家加群留言。

同程旅行基于 RocketMQ 高可用架構實踐背景介紹MQ 雙中心改造MQ 平台治理