基於消息隊列 RocketMQ 的大型分布式應用上雲最佳實踐


作者|紹舒
審核&校對:歲月、佳佳
編輯&排版:雯燕

前言

消息隊列是分布式互聯網架構的重要基礎設施,在以下場景都有着重要的應用:

  • 應用解耦
  • 削峰填谷
  • 異步通知
  • 分布式事務
  • 大數據處理

並涉及互動直播、移動互聯網&物聯網,IM 實時通信、Cache 同步、日志監控等多個領域。

而本文主要圍繞着商業版本的消息隊列 RocketMQ,和開源版本 RocketMQ 進行比較,並結合一些實踐中的場景來展示大型分布式應用的上雲最佳實踐。

1.png

核心能力

商業版本消息隊列 RocketMQ 相比較開源版本 RocketMQ 和其他競品,主要有以下幾點優勢。

  1. 開箱即用、功能豐富
  2. 高性能、無限擴展能力
  3. 可觀測、免運維能力
  4. 高 SLA 和穩定性保證

2.png

開箱即用、功能豐富

消息隊列 RocketMQ 提供了定時、事務、順序等多類型消息的支持,且支持廣播、集群兩種消費模式;另外在協議層面,提供 TCP/HTTP 多協議支持,還提供了 TAG/SQL 屬性過濾功能,極大程度地拓寬了用戶的使用場景。

高性能、無限拓展能力

消息隊列 RocketMQ 經受了阿里核心電商歷年雙十一洪峰的考驗,支持千萬級 TPS 消息收發和億級消息堆積的能力,並且能夠為消息提供毫秒級端到端延遲保障,另外還提供分級存儲,支持海量消息的任意保存時間。

可觀測、免運維能力

消息隊列 RocketMQ 提供了一個可觀測性大盤,支持細粒度數據大盤,提供了消息全鏈路生命周期追蹤和查詢能力,對各個指標提供了相應的監控報警功能;此外,還提供了消息回溯和死信隊列功能,能夠保證用戶的消息能夠隨時回溯消費。

高 SLA 和穩定性保障

消息隊列 RocketMQ 的穩定性是我們一貫、持續、穩定投入的重要領域,提供了高可用部署和多副本寫入功能;另外也支持同城多 AZ 容災和異地多活。

產品剖面

接下來,我們會從以上的產品核心能力中挑選幾個剖面,並且結合具體的場景和實踐來做進一步的介紹。

多消息類型支持

高可用順序消息

商業版本消息隊列 RocketMQ 使用的順序消息我們稱之為高可用順序消息。在介紹高可用順序消息之前,首先簡要介紹下開源版本 RocketMQ 的順序消息。

順序消息分為兩種類型,全局順序消息和分區順序消息。

  • 全局順序消息:在 RocketMQ 存儲層只會分配一個分區,也就是說全局順序 Topic 的可用性跟單一副本的可用性強相關,且不具備可擴展的能力。
  • 分區順序消息:所有消息根據 Sharding Key 進行分區。同一個分區內的消息按照嚴格的 FIFO 順序進行發布和消費。Sharding Key 是順序消息中用來區分不同分區的關鍵字段。

下圖是分區順序消息的應用場景,order ID 即為此時順序消息的 Sharding Key。

3.png

可以看到,無論是全局順序消息還是分區順序消息,都依賴了單一分區天然的 FIFO 特性來保證順序,因此順序性也只能在同一個分區內保證,當此分區所在的副本不可用時,順序消息並不具備重試到其他副本的能力,此時消息的順序性就難以得到保證。

為了解決這一問題,我們設計並實現了高可用順序消息。

高可用順序消息有以下幾個特點:

  • 一個邏輯順序分區(PartitionGroup)下有多個物理分區。
  • 其中任意一個物理分區是可寫的,那么整個邏輯分區是可寫且有序的。
  • 我們基於 happened-before 的原則設計了一套基於分區位點的排序算法。
  • 根據該算法,消費者在消費某一邏輯分區時,會從其所屬的各個物理分區中拉取消息並進行合並排序,得出正確的消息順序流。

4.png

通過這樣的設計,高可用順序消息解決了下列幾點問題:

  • 可用性問題:高可用順序消息將具備與普通消息一致的可用性,在某副本不可用時,可快速重試至其它副本。
  • 可擴展性問題:普通順序消息,特別是普通全局順序消息,不具備良好的擴展能力,只能固定在特定的副本中。高可用順序消息的邏輯順序分區可以將物理順序分區分散在多個副本中。
  • 熱點問題:普通順序消息根據 Key 將一類消息 Hash 至同一個分區中,熱點 Key 會導致熱點分區,高可用順序消息具備橫向擴展能力,可以為邏輯順序分區添加多個物理分區來消除熱點問題。
  • 單點問題:普通全局順序消息,僅包含單分區,極易出現單點故障,高可用順序消息可以消除全局順序消息的單點問題。

尤其需要注意的是熱點問題,在阿里巴巴內部某電商業務大促時,因發送到順序 Topic 的某一特定的 ShardingKey 數量過多,集群中一個副本接收到了大量該 ShardingKey 的消息,導致該副本超出其負荷上限,造成了消息的延遲和堆積,一定程度上影響了業務。在使用了高可用順序消息之后,由於其在多物理分區中的負載均衡特性,提升了集群順序消息的承載能力,從而避免了熱點問題的出現。

秒級精准定時消息

定時消息,是指客戶端當前發送但希望在未來的某個時間內收到的消息。定時消息廣泛應用於各類調度系統或者業務系統之中。比如支付訂單,產生一個支付消息,系統通常需要在一定時間后處理該消息,判斷用戶是否支付成功,然后系統做相應處理。

開源版本的 RocketMQ 只支持幾個指定的延遲級別,並不支持秒級精度的定時消息。而面向集團內和雲上多樣化的需求,開源版本的定時消息並不能滿足我們的需求,因此我們推出了秒級精准定時消息。

5.png

如下圖所示,我們基於時間輪設計並實現了支持任意定時時間的秒級精准定時消息,同時滿足以下特性:

  • 任意定時時間
  • 超長定時時間
  • 海量定時消息
  • 刪除定時消息
  • 高可用
  • 高性能

6.png

內部某用戶有這樣的場景,期望在未來的某一分鍾的 30s 時刻處理這樣一個定時請求,開源版本的定時消息並不符合其需要,而秒級精准定時消息在保證高可用、高性能的同時,滿足了其業務需求。

分布式事務消息

如下圖所示,在傳統的事務處理中,多個系統之間的交互耦合到一個事務中,造成整體的相應時間長,回滾過程復雜,從而潛在影響了系統的可用性;而 RocketMQ 提供的分布式事務功能,在保證了系統松耦合和數據最終一致性的前提下,實現了分布式事務。

7.png

消息隊列 RocketMQ 提供的事務消息處理步驟如下:

  • 發送方將半事務消息發送至消息隊列 RocketMQ 版服務端。
  • 消息隊列 RocketMQ 版服務端將消息持久化成功之后,向發送方返回 Ack 確認消息已經發送成功,此時消息為半事務消息。
  • 發送方開始執行本地事務邏輯。
  • 發送方根據本地事務執行結果向服務端提交二次確認(Commit 或是 Rollback),服務端收到 Commit 狀態則將半事務消息標記為可投遞,訂閱方最終將收到該消息;服務端收到 Rollback 狀態則刪除半事務消息,訂閱方將不會接受該消息。

基於這樣的實現,我們通過消息實現了分布式事務特性,即本地事務的執行結果會最終反應到訂閱方是否能接收到該條消息。

8.png

消息隊列 RocketMQ 的分布式事務消息廣泛地應用於阿里巴巴核心交易鏈路中,通過分布式事務消息,實現了最小事務單元;交易系統和消息隊列之間,組成一個事務處理;下游系統(購物車、積分、其它)相互隔離,並行處理。

分級存儲

背景

隨着雲上客戶的不斷增多,存儲逐漸成為 RocketMQ 運維的重要瓶頸,這包括並且不限於:

  • 內存大小有限,服務端不能將所有用戶的數據全部緩存在內存中;在多租戶場景下,當有用戶拉取冷數據時,會對磁盤造成較大 IO 壓力,從而影響共享集群的其他用戶,亟需做到數據的冷熱分離。
  • 雲上有單租戶定制化消息存儲時長的需求。而 RocketMQ Broker 中所有用戶的消息是放在一個連續文件中進行存儲的,無法針對任何單一用戶定制存儲時長,即現有的存儲結構無法滿足這樣的需求。
  • 如果能對海量數據提供更低成本的存儲方式,可以大幅降低雲上 RocketMQ 的磁盤存儲成本。

基於以上現狀,分級存儲方案應運而生。

架構

分級存儲的整體架構如下:

  1. connector 節點負責將 broker 上的消息實時同步到 OSS 上
  2. historyNode 節點將用戶對冷數據的拉取請求轉發至 OSS 上
  3. 在 OSS 中是按照 Queue 粒度來組織文件結構的,即每個 Queue 會由獨立的文件進行存儲,從而保證了我們可以針對於租戶定義消息的存儲時長。

9.png

通過這樣的設計,我們實現了消息數據的冷熱分離。

10.png

使用場景

基於分級存儲,我們進一步拓展了用戶的使用場景:

  1. 自定義存儲時間:在消息數據的冷熱分離之后,我們將冷數據存儲到 OSS 這樣的存儲系統中,能夠實現用戶自定義的存儲時間。
  2. 消息審計:在消息的存儲之間從數天擴展到自定義后,消息的屬性從一個臨時性的中轉數據變成了用戶的數據資產,而消息系統也從數據中樞轉變成了數據倉庫;用戶能夠基於數據倉庫實現更多樣的審計、分析、處理功能。
  3. 消息回放:在流計算場景中,消息回放是非常重要的一個場景;通過拓展消息的存儲時間之后,流計算能夠實現更加豐富的計算分析場景。

穩定性

消息隊列 RocketMQ 的穩定性是我們一貫、持續、穩定投入的重要領域。在介紹我們在穩定性的最新工作之前,首先帶大家回顧下 RocketMQ 高可用架構的演進路線。

高可用架構演進路線

2012 年,RocketMQ 作為阿里巴巴全新一代的消息引擎問世,並隨后開源至社區,第一代 RocketMQ 高可用架構也隨之誕生。如下圖所示,第一代高可用架構采取當時流行的 Master-Slave 主從架構,寫流量經過 Master 節點同步至 Slave 節點,讀流量也經過 Master 節點並將消費記錄同步至 Slave 節點。當 Master 節點不可用時,整個副本組可讀不可寫。

11.png

2016 年,RocketMQ 雲產品正式開始商業化,雲時代單點故障頻發,雲產品需要完全面向失敗而設計,因此 RocketMQ 推出了第二代多副本架構,依托於 Zookeeper 的分布式鎖和通知機制,引入 Controller 組件負責 Broker 狀態的監控以及主備狀態機轉換,在主不可用時,備自動切換為主。第二代架構是消息雲產品規模化進程中的核心高可用架構,為雲產品規模化立下了汗馬功勞。

2018 年,RocketMQ 社區對 Paxos 和 Raft 引入分布式協議有極大的熱情,RocketMQ 研發團隊在開源社區推出了基於 Raft 協議的 Dledger 存儲引擎,原生支持 Raft 多副本。

RocketMQ 高可用架構已經走過了三代,在集團、公有雲和專有雲多樣場景的實踐中,我們發現這三套高可用架構都存在一些弊端:

  • 第一代主備架構只起到了冷備的作用,且主備切換需要人工介入,在大規模場景下有較大的資源浪費以及運維成本。
  • 第二代架構引入了 Zookeeper 和 Controller 節點,架構上更加復雜,在主備切換做到了自動化,但故障轉移時間較長,一般是 10 秒左右完成選主。
  • 第三代 Raft 架構目前暫未在雲上和阿里集團內大規模應用,且 Raft 協議就決定了需要選主,新主還需要被客戶端路由發現,整個故障轉移時間依然較長;另外,強一致的 Raft 版本並未支持靈活的降級策略,無法在可用性和可靠性之間做靈活的權衡。

為了應對雲上日益增長的業務規模、更嚴苛的 SLA 要求、復雜多變的專有雲部署環境,當前的消息系統需要一種架構簡單、運維簡單、有基於當前架構落地路徑的方案,我們將其稱作秒級 RTO 多副本架構。

新一代秒級 RTO 多副本架構

秒級 RTO 多副本架構是消息中間件團隊設計實現的新一代高可用架構,包含副本組成機制、Failover 機制、對現有組件的侵入性修改等。

整個副本組有以下特點:

  • Strong Leader/No Election:Leader 在部署時確定,整個生命周期內不會發生切換,但可在故障時被替換。
  • 僅 Leader 支持消息寫入:每一個副本組僅 Leader 接受消息寫入,Leader 不可用時,整個副本組不可寫入。
  • 所有的副本支持消息讀取:雖然 Leader 上擁有全量的消息,Follower 上的消息量不對等,但所有的副本都支持消息的讀取。
  • 靈活的副本組數量:可以基於可靠性、可用性和成本自由選擇副本組的數量。
  • 靈活的 Quorum 數量:最終所有的消息都會同步到整個副本組上,但副本組內可以靈活配置寫成功最小副本數。例如 2-3 模式,3 副本情況下,2 副本成功即為寫成功。同時,在副本不可用的情況下,Quorum 數量也可以動態自行降級。

在上述副本組的概念下,故障轉移可以復用當前 RocketMQ 客戶端的機制來完成。如下圖所示:

12.png

  1. Producer 在主不可用時,靈活快速地切換至另一個副本組。
  2. Consumer 在某個副本不可用時可快速切換至同副本組另一個副本上進行消息消費。

可觀測性

健康大盤

我們在可觀測性方面也做了大量的工作,為用戶提供了一個消息系統的可觀測性健康數據大盤。如下圖所示,用戶能夠清晰的看到實例級別、topic 級別、group 級別的各種監控數據,能夠全方面地監控、診斷問題。

13.png

消息鏈路追蹤

另外我們還基於消息軌跡提供了消息全鏈路軌跡追蹤功能。如下圖所示,用戶能夠在控制台上看到完整的消息生命周期、從消息的發送、存儲、到消費,整個鏈路都能被完整地記錄下來。

14.png

應用場景

客戶痛點:業務出現消費堆積的用戶需要根據消息軌跡抽樣數據,綜合分析后才能大致判斷引起問題原因,排查困難。

核心價值:提高線上運行問題排查的效率,和問題定位的准確性。直接在健康大盤上快速發現風險最高的 Topic 和 Group,並根據各個指標的變化情況快速定位原因。例如消息處理時間過長可以擴容消費者機器或優化消費業務邏輯,如果是失敗率過高可以快速查看日志排除錯誤原因。

事件驅動

大家一定非常熟悉 Gartner,在2018年的一個評估報告里,Gartner 將 Event-Driven Model,列為了未來10大戰略技術趨勢之一,並且,做出了兩個預測:

  • 2022年,超過 60% 的新型數字化商業解決方案,都會采用事件通知的軟件模型。
  • 2022年,超過 50% 的商業組織,將會參與到EDA生態系統當中去。

同一年,CNCF 基金會也提出了 CloudEvents,意在規范不同雲服務之間的事件通訊協議標准。到目前為止,CloudEvents也已經發布了多個消息中間件的綁定規范。

可見事件驅動是未來業務系統的一個重要趨勢,而消息天然具備和事件的親近性,因此消息隊列 RocketMQ,是堅決擁抱事件驅動的。

談到消息和事件,這里做一個簡單的闡述:消息和事件是兩種不同形態的抽象,也意味着滿足不同的場景:

  • 消息:消息是比事件更通用的抽象,常用於微服務調用之間的異步解耦,微服務調用之間往往需要等到服務能力不對等時才會去通過消息對服務調用進行異步化改造;消息的內容往往綁定了較強的業務屬性,消息的發送方對消息處理邏輯是有明確的預期的。
  • 事件:事件相對於消息更加具像化,代表了事情的發送、條件和狀態的變化;事件源來自不同的組織和環境,所以事件總線天然需要跨組織;事件源對事件將被如何響應沒有任何預期的,所以采用事件的應用架構是更徹底的解耦,采用事件的應用架構將更加具備可擴展性和靈活性。

在2020年,阿里雲發布了事件總線 EventBridge 這一產品,其使命是作為雲事件的樞紐,以標准化的 CloudEvents 1.0 協議連接雲產品和雲應用,提供中心化的事件治理和驅動能力,幫助用戶輕松構建松耦合、分布式的事件驅動架構;另外,在阿里雲之外的雲市場上有海量垂直領域的 SaaS 服務,EventBridge 將以出色的跨產品、跨組織以及跨雲的集成與被集成能力,助力客戶打造一個完整的、事件驅動的、高效可控的上雲新界面。

而借助事件總線 EventBridge 提供的事件源功能,我們能夠打通消息到事件的鏈路,使得消息隊列 RocketMQ 具備事件驅動的動力,從而擁抱整個事件生態。接下來我們將借助一個案例,如下圖所示,為大家展示這一功能。

15.png

創建消息隊列 RocketMQ 主題

16.png

創建目標服務

我們基於容器服務快速創建一個事件驅動的服務,計算負載 Deployment 的 yaml 如下,該服務能夠響應事件並將結果打印到標准輸出中。

apiVersion: apps/v1 # for versions before 1.8.0 use apps/v1beta1
kind: Deployment
metadata:
  name: eventbridge-http-target-deployment
  labels:
    app: eventbridge-http-target
spec:
  replicas: 2
  selector:
    matchLabels:
      app: eventbridge-http-target
  template:
    metadata:
      labels:
        app: eventbridge-http-target
    spec:
      containers:
      - name: eb-http-target
        # 下述鏡像暴露了一個 HTTP 地址(/cloudevents)用於接收 CloudEvents,源碼參考:https://github.com/aliyuneventbridge/simple-http-target
        image: registry.cn-hangzhou.aliyuncs.com/eventbridge-public/simple-http-target:latest
        ports:
        - containerPort: 8080

前往容器服務控制台,進入服務與路由的服務頁面,創建一個私網訪問類型的 Service,並做好端口映射。

17.png

創建事件總線 EventBridge 自定義總線

我們來到事件總線 EventBridge 控制台,創建一個自定義總線 demo-with-k8s。

18.png

創建事件總線 EventBridge 自定義總線規則

我們為總線 demo-with-k8s 創建一個規則,並選擇 HTTP 作為事件目標,選擇專有網絡類型,選中對應的 VPC、 VSwitch 以及安全組,並指定目標URL,如下圖所示:

19.png

創建事件總線 EventBridge 事件源

我們為該自定義事件總線添加消息隊列 RocketMQ 版的自定義事件源。

20.png

發送 RocketMQ 消息

接下來我們回到消息隊列 RocketMQ 控制台,通過控制台的快速體驗消息生產功能發送一條內容為 hello eventbridge 的消息到對應的主題中去。

21.png

接下來我們就可以發現,這條 RocketMQ 消息,以 CloudEvent 的形式被投遞到了對應的服務中去,我們從而打通了消息到事件的鏈路。同時,基於我們上述提到的分級存儲功能,消息隊列 RocketMQ 轉變成了一個能夠源源不斷提供事件的數據倉庫,為整個事件生態提供了更加廣闊的場景。

事件驅動是未來商業組織和業務系統的重要趨勢,而消息隊列 RocketMQ 會堅定地擁抱這一趨勢,將消息融入到事件的生態中。

總結

我們選取了消息隊列 RocketMQ 的幾個產品剖面,從多消息類型、分級存儲到穩定性、可觀測性,再到面向未來的事件驅動,並結合與開源 RocketMQ 的對比,及具體應用場景的分析,為大家展示了基於消息隊列 RocketMQ 的大型分布式應用上雲最佳實踐。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM