日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

同程旅行基于 RocketMQ 高可用架构实践

發(fā)布時(shí)間:2025/3/20 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 同程旅行基于 RocketMQ 高可用架构实践 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

背景介紹

?

為何選擇 RocketMQ

?

我們?cè)趲啄昵皼Q定引入 MQ 時(shí),市場(chǎng)上已經(jīng)有不少成熟的解決方案,比如 RabbitMQ , ActiveMQ,NSQ,Kafka 等。考慮到穩(wěn)定性、維護(hù)成本、公司技術(shù)棧等因素,我們選擇了 RocketMQ :
?

  • 純 Java 開(kāi)發(fā),無(wú)依賴,使用簡(jiǎn)單,出現(xiàn)問(wèn)題能 hold ;
  • 經(jīng)過(guò)阿里雙十一考驗(yàn),性能、穩(wěn)定性可以保障;
  • 功能實(shí)用,發(fā)送端:同步、異步、單邊、延時(shí)發(fā)送;消費(fèi)端:消息重置,重試隊(duì)列,死信隊(duì)列;
  • 社區(qū)活躍,出問(wèn)題能及時(shí)溝通解決。

?

使用情況

?

  • 主要用于削峰、解耦、異步處理;
  • 已在火車票、機(jī)票、酒店等核心業(yè)務(wù)廣泛使用,扛住巨大的微信入口流量;
  • 在支付、訂單、出票、數(shù)據(jù)同步等核心流程廣泛使用;
  • 每天 1000+ 億條消息周轉(zhuǎn)。

?

下圖是 MQ 接入框架圖
?

由于公司技術(shù)棧原因,client sdk 我們提供了 java sdk ;對(duì)于其他語(yǔ)言,收斂到 http proxy ,屏蔽語(yǔ)言細(xì)節(jié),節(jié)約維護(hù)成本。按照各大業(yè)務(wù)線,對(duì)后端存儲(chǔ)節(jié)點(diǎn)進(jìn)行了隔離,相互不影響。
?

MQ 雙中心改造

?

之前單機(jī)房出現(xiàn)過(guò)網(wǎng)絡(luò)故障,對(duì)業(yè)務(wù)影響較大。為保障業(yè)務(wù)高可用,同城雙中心改造提上了日程。
?

為何做雙中心

?

  • 單機(jī)房故障業(yè)務(wù)可用;?
  • 保證數(shù)據(jù)可靠:若所有數(shù)據(jù)都在一個(gè)機(jī)房,一旦機(jī)房故障,數(shù)據(jù)有丟失風(fēng)險(xiǎn);
  • 橫向擴(kuò)容:單機(jī)房容量有限,多機(jī)房可分擔(dān)流量。

?

雙中心方案

?

做雙中心之前,對(duì)同城雙中心方案作了些調(diào)研,主要有冷(熱)備份、雙活兩種。(當(dāng)時(shí)社區(qū) Dledger 版本還沒(méi)出現(xiàn),Dledger 版本完全可做為雙中心的一種可選方案。)
?

1)同城冷(熱)備份
?

兩個(gè)獨(dú)立的 MQ 集群, 用戶流量寫(xiě)到一個(gè)主集群,數(shù)據(jù)實(shí)時(shí)同步到備用集群,社區(qū)有成熟的 RocketMQ Replicator 方案,需要定期同步元數(shù)據(jù),比如主題,消費(fèi)組,消費(fèi)進(jìn)度等。
?

2)同城雙活
?

兩個(gè)獨(dú)立 MQ 集群,用戶流量寫(xiě)到各自機(jī)房的 MQ 集群,數(shù)據(jù)相互不同步。
?

平時(shí)業(yè)務(wù)寫(xiě)入各自機(jī)房的 MQ 集群,若一個(gè)機(jī)房掛了,可以將用戶請(qǐng)求流量全部切到另一個(gè)機(jī)房,消息也會(huì)生產(chǎn)到另一個(gè)機(jī)房。
?

對(duì)于雙活方案,需要解決 MQ 集群域名。

1)若兩個(gè)集群用一個(gè)域名,域名可以動(dòng)態(tài)解析到各自機(jī)房。此方式要求生產(chǎn)、消費(fèi)必須在同一個(gè)機(jī)房。假如生產(chǎn)在 idc1 ,消費(fèi)在 idc2 ,這樣生產(chǎn)、消費(fèi)各自連接一個(gè)集群,沒(méi)法消費(fèi)數(shù)據(jù)。

2)若一個(gè)集群一個(gè)域名,業(yè)務(wù)方改動(dòng)較大,我們之前對(duì)外服務(wù)的集群是單中心部署的,業(yè)務(wù)方已經(jīng)大量接入,此方案推廣較困難。

為盡可能減少業(yè)務(wù)方改動(dòng),域名只能繼續(xù)使用之前的域名,最終我們采用一個(gè) Global MQ 集群,跨雙機(jī)房,無(wú)論業(yè)務(wù)是單中心部署還是雙中心部署都不影響;而且只要升級(jí)客戶端即可,無(wú)需改動(dòng)任何代碼。

雙中心訴求

?

  • 就近原則:生產(chǎn)者在 A 機(jī)房,生產(chǎn)的消息存于 A 機(jī)房 broker ; 消費(fèi)者在 A 機(jī)房,消費(fèi)的消息來(lái)自 A 機(jī)房 broker 。
  • 單機(jī)房故障:生產(chǎn)正常,消息不丟。
  • broker 主節(jié)點(diǎn)故障:自動(dòng)選主。

就近原則

?

簡(jiǎn)單說(shuō),就是確定兩件事:

  • 節(jié)點(diǎn)(客戶端節(jié)點(diǎn),服務(wù)端節(jié)點(diǎn))如何判斷自己在哪個(gè) idc;
  • 客戶端節(jié)點(diǎn)如何判斷服務(wù)端節(jié)點(diǎn)在哪個(gè) idc。

如何判斷自己在哪個(gè) idc?
?

  • ip 查詢
    節(jié)點(diǎn)啟動(dòng)時(shí)可以獲取自身 ip ,通過(guò)公司內(nèi)部的組件查詢所在的機(jī)房。
    ?
  • 2)環(huán)境感知
    需要與運(yùn)維同學(xué)一起配合,在節(jié)點(diǎn)裝機(jī)時(shí),將自身的一些元數(shù)據(jù),比如機(jī)房信息等寫(xiě)入本地配置文件,啟動(dòng)時(shí)直接讀寫(xiě)配置文件即可。

    我們采用了第二個(gè)方案,無(wú)組件依賴,配置文件中 logicIdcUK 的值為機(jī)房標(biāo)志。
    ?

    客戶端節(jié)點(diǎn)如何識(shí)別在同一個(gè)機(jī)房的服務(wù)端節(jié)點(diǎn)?
    ?

    客戶端節(jié)點(diǎn)可以拿到服務(wù)端節(jié)點(diǎn)的 ip 以及 broker 名稱的,因此:
    ?

    • ip 查詢:通過(guò)公司內(nèi)部組件查詢 ip 所在機(jī)房信息;
    • broker 名稱增加機(jī)房信息:在配置文件中,將機(jī)房信息添加到 broker 名稱上;
    • 協(xié)議層增加機(jī)房標(biāo)識(shí):服務(wù)端節(jié)點(diǎn)向元數(shù)據(jù)系統(tǒng)注冊(cè)時(shí),將自身的機(jī)房信息一起注冊(cè)。

    相對(duì)于前兩者,實(shí)現(xiàn)起來(lái)略復(fù)雜,改動(dòng)了協(xié)議層, 我們采用了第二種與第三種結(jié)合的方式。

    就近生產(chǎn)

    ?

    基于上述分析,就近生產(chǎn)思路很清晰,默認(rèn)優(yōu)先本機(jī)房就近生產(chǎn);
    ?

    若本機(jī)房的服務(wù)節(jié)點(diǎn)不可用,可以嘗試擴(kuò)機(jī)房生產(chǎn),業(yè)務(wù)可以根據(jù)實(shí)際需要具體配置。

    就近消費(fèi)

    ?

    優(yōu)先本機(jī)房消費(fèi),默認(rèn)情況下又要保證所有消息能被消費(fèi)。
    ?

    隊(duì)列分配算法采用按機(jī)房分配隊(duì)列
    ?

    • 每個(gè)機(jī)房消息平均分給此機(jī)房消費(fèi)端;
    • 此機(jī)房沒(méi)消費(fèi)端,平分給其他機(jī)房消費(fèi)端。

    ?

    偽代碼如下:
    ?

    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為當(dāng)前客戶端 }

    ?

    消費(fèi)場(chǎng)景主要是消費(fèi)端單邊部署與雙邊部署。
    ?

    單邊部署時(shí),消費(fèi)端默認(rèn)會(huì)拉取每個(gè)機(jī)房的所有消息。

    雙邊部署時(shí),消費(fèi)端只會(huì)消費(fèi)自己所在機(jī)房的消息,要注意每個(gè)機(jī)房的實(shí)際生產(chǎn)量與消費(fèi)端的數(shù)量,防止出現(xiàn)某一個(gè)機(jī)房消費(fèi)端過(guò)少。

    單機(jī)房故障

    ?

    • 每組 broker 配置

    一主兩從,一主一從在一機(jī)房,一從在另一機(jī)房;某一從同步完消息,消息即發(fā)送成功。
    ?

    • 單機(jī)房故障

    消息生產(chǎn)跨機(jī)房;未消費(fèi)消息在另一機(jī)房繼續(xù)被消費(fèi)。

    故障切主

    ?

    在某一組 broker 主節(jié)點(diǎn)出現(xiàn)故障時(shí),為保障整個(gè)集群的可用性,需要在 slave 中選主并切換。要做到這一點(diǎn),首先得有個(gè)broker 主故障的仲裁系統(tǒng),即 nameserver(以下簡(jiǎn)稱 ns )元數(shù)據(jù)系統(tǒng)(類似于 redis 中的哨兵)。
    ?

    ns 元數(shù)據(jù)系統(tǒng)中的節(jié)點(diǎn)位于三個(gè)機(jī)房(有一個(gè)第三方的云機(jī)房,在云上部署 ns 節(jié)點(diǎn),元數(shù)據(jù)量不大,延時(shí)可以接受),三個(gè)機(jī)房的 ns 節(jié)點(diǎn)通過(guò) raft 協(xié)議選一個(gè)leader,broker 節(jié)點(diǎn)會(huì)將元數(shù)據(jù)同步給 leader, leader 在將元數(shù)據(jù)同步給 follower 。
    ?

    客戶端節(jié)點(diǎn)獲取元數(shù)據(jù)時(shí), 從 leader,follower 中均可讀取數(shù)據(jù)。
    ?

    切主流程

    ?

    • 若 nameserver leader 監(jiān)控到 broker 主節(jié)點(diǎn)異常, 并要求其他 follower 確認(rèn);半數(shù) follower 認(rèn)為 broker 節(jié)點(diǎn)異常,則 leader 通知在 broker 從節(jié)點(diǎn)中選主,同步進(jìn)度大的從節(jié)點(diǎn)選為主;
    • 新選舉的 broker 主節(jié)點(diǎn)執(zhí)行切換動(dòng)作并注冊(cè)到元數(shù)據(jù)系統(tǒng);
    • 生產(chǎn)端無(wú)法向舊 broker 主節(jié)點(diǎn)發(fā)送消息。

    ?

    流程圖如下

    切中心演練
    ?

    用戶請(qǐng)求負(fù)載到雙中心,下面的操作先將流量切到二中心—回歸雙中心—切到一中心。確保每個(gè)中心均可承擔(dān)全量用戶請(qǐng)求。

    先將用戶流量全部切到二中心

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

    回顧

    • 全局 Global 集群
    • 就近原則
    • 一主二從,寫(xiě)過(guò)半消息即及寫(xiě)入成功
    • 元數(shù)據(jù)系統(tǒng) raft 選主
    • broker 主節(jié)點(diǎn)故障,自動(dòng)選主

    ?

    MQ 平臺(tái)治理

    ?

    即使系統(tǒng)高性能、高可用,倘若隨便使用或使用不規(guī)范,也會(huì)帶來(lái)各種各樣的問(wèn)題,增加了不必要的維護(hù)成本,因此必要的治理手段不可或缺。
    ?

    目的

    ?讓系統(tǒng)更穩(wěn)定

    • 及時(shí)告警
    • 快速定位、止損

    ?

    治理哪些方面

    ?

    主題/消費(fèi)組治理
    ?

    • 申請(qǐng)使用

    生產(chǎn)環(huán)境 MQ 集群,我們關(guān)閉了自動(dòng)創(chuàng)建主題與消費(fèi)組,使用前需要先申請(qǐng)并記錄主題與消費(fèi)組的項(xiàng)目標(biāo)識(shí)與使用人。一旦出現(xiàn)問(wèn)題,我們能夠立即找到主題與消費(fèi)組的負(fù)責(zé)人,了解相關(guān)情況。若存在測(cè)試,灰度,生產(chǎn)等多套環(huán)境,可以一次申請(qǐng)多個(gè)集群同時(shí)生效的方式,避免逐個(gè)集群申請(qǐng)的麻煩。
    ?

    • 生產(chǎn)速度

    為避免業(yè)務(wù)疏忽發(fā)送大量無(wú)用的消息,有必要在服務(wù)端對(duì)主題生產(chǎn)速度進(jìn)行流控,避免這個(gè)主題擠占其他主題的處理資源。
    ?

    • 消息積壓

    對(duì)消息堆積敏感的消費(fèi)組,使用方可設(shè)置消息堆積數(shù)量的閾值以及報(bào)警方式,超過(guò)這個(gè)閾值,立即通知使用方;亦可設(shè)置消息堆積時(shí)間的閾值,超過(guò)一段時(shí)間沒(méi)被消費(fèi),立即通知使用方。
    ?

    • 消費(fèi)節(jié)點(diǎn)掉線

    消費(fèi)節(jié)點(diǎn)下線或一段時(shí)間無(wú)響應(yīng),需要通知給使用方。

    客戶端治理
    ?

    • 發(fā)送、消費(fèi)耗時(shí)檢測(cè)

    監(jiān)控發(fā)送/消費(fèi)一條消息的耗時(shí),檢測(cè)出性能過(guò)低的應(yīng)用,通知使用方著手改造以提升性能;同時(shí)監(jiān)控消息體大小,對(duì)消息體大小平均超過(guò) 10 KB 的項(xiàng)目,推動(dòng)項(xiàng)目啟用壓縮或消息重構(gòu),將消息體控制在 10 KB 以內(nèi)。
    ?

    • 消息鏈路追蹤

    一條消息由哪個(gè) ip 、在哪個(gè)時(shí)間點(diǎn)發(fā)送,又由哪些 ip 、在哪個(gè)時(shí)間點(diǎn)消費(fèi),再加上服務(wù)端統(tǒng)計(jì)的消息接收、消息推送的信息,構(gòu)成了一條簡(jiǎn)單的消息鏈路追蹤,將消息的生命周期串聯(lián)起來(lái),使用方可通過(guò)查詢msgId或事先設(shè)置的 key 查看消息、排查問(wèn)題。
    ?

    • 過(guò)低或有隱患版本檢測(cè)

    隨著功能的不斷迭代,sdk 版本也會(huì)升級(jí)并可能引入風(fēng)險(xiǎn)。定時(shí)上報(bào) sdk 版本,推動(dòng)使用方升級(jí)有問(wèn)題或過(guò)低的版本。

    服務(wù)端治理
    ?

    • 集群健康巡檢

    如何判斷一個(gè)集群是健康的?定時(shí)檢測(cè)集群中節(jié)點(diǎn)數(shù)量、集群寫(xiě)入 tps 、消費(fèi) tps ,并模擬用戶生產(chǎn)、消費(fèi)消息。
    ?

    • 集群性能巡檢

    性能指標(biāo)最終反映在處理消息生產(chǎn)與消費(fèi)的時(shí)間上。服務(wù)端統(tǒng)計(jì)處理每個(gè)生產(chǎn)、消費(fèi)請(qǐng)求的時(shí)間,一個(gè)統(tǒng)計(jì)周期內(nèi),若存在一定比例的消息處理時(shí)間過(guò)長(zhǎng),則認(rèn)為這個(gè)節(jié)點(diǎn)性能有問(wèn)題;引起性能問(wèn)題的原因主要是系統(tǒng)物理瓶頸,比如磁盤(pán) io util 使用率過(guò)高,cpu load 高等,這些硬件指標(biāo)通過(guò)夜鷹監(jiān)控系統(tǒng)自動(dòng)報(bào)警。
    ?

    • 集群高可用

    高可用主要針對(duì) broker 中 master 節(jié)點(diǎn)由于軟硬件故障無(wú)法正常工作,slave 節(jié)點(diǎn)自動(dòng)被切換為 master ,適合消息順序、集群完整性有要求的場(chǎng)景。
    ?

    部分后臺(tái)操作展示

    主題與消費(fèi)組申請(qǐng)

    生產(chǎn),消費(fèi),堆積實(shí)時(shí)統(tǒng)計(jì)
    ?

    ?
    集群監(jiān)控

    踩過(guò)的坑
    ?

    社區(qū)對(duì) MQ 系統(tǒng)經(jīng)歷了長(zhǎng)時(shí)間的改進(jìn)與沉淀,我們?cè)谑褂眠^(guò)程中也到過(guò)一些問(wèn)題,要求我們能從深入了解源碼,做到出現(xiàn)問(wèn)題心不慌,快速止損。
    ?

    • 新老消費(fèi)端并存時(shí),我們實(shí)現(xiàn)的隊(duì)列分配算法不兼容,做到兼容即可;
    • 主題、消費(fèi)組數(shù)量多,注冊(cè)耗時(shí)過(guò)長(zhǎng),內(nèi)存 oom ,通過(guò)壓縮縮短注冊(cè)時(shí)間,社區(qū)已修復(fù);
    • topic 長(zhǎng)度判斷不一致,導(dǎo)致重啟丟消息,社區(qū)已修復(fù);
    • centos 6.6 版本中,broker 進(jìn)程假死,升級(jí) os 版本即可。

    MQ 未來(lái)展望

    ?

    目前消息保留時(shí)間較短,不方便對(duì)問(wèn)題排查以及數(shù)據(jù)預(yù)測(cè),我們接下來(lái)將對(duì)歷史消息進(jìn)行歸檔以及基于此的數(shù)據(jù)預(yù)測(cè)。
    ?

    • 歷史數(shù)據(jù)歸檔
    • 底層存儲(chǔ)剝離,計(jì)算與存儲(chǔ)分離
    • 基于歷史數(shù)據(jù),完成更多數(shù)據(jù)預(yù)測(cè)
    • 服務(wù)端升級(jí)到 Dledger ,確保消息的嚴(yán)格一致

    ?

    了解更多 RocketMQ 信息,可加入社區(qū)交流群,下面是釘釘群,歡迎大家加群留言。
    ?

    總結(jié)

    以上是生活随笔為你收集整理的同程旅行基于 RocketMQ 高可用架构实践的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。