基于消息队列 RocketMQ 的大型分布式应用上云最佳实践
作者|紹舒
審核&校對:歲月、佳佳
編輯&排版:雯燕
前言
消息隊列是分布式互聯網架構的重要基礎設施,在以下場景都有著重要的應用:
- 應用解耦
 - 削峰填谷
 - 異步通知
 - 分布式事務
 - 大數據處理
 
并涉及互動直播、移動互聯網&物聯網,IM 實時通信、Cache 同步、日志監控等多個領域。
而本文主要圍繞著商業版本的消息隊列 RocketMQ,和開源版本 RocketMQ 進行比較,并結合一些實踐中的場景來展示大型分布式應用的上云最佳實踐。
核心能力
商業版本消息隊列 RocketMQ 相比較開源版本 RocketMQ 和其他競品,主要有以下幾點優勢。
開箱即用、功能豐富
消息隊列 RocketMQ 提供了定時、事務、順序等多類型消息的支持,且支持廣播、集群兩種消費模式;另外在協議層面,提供 TCP/HTTP 多協議支持,還提供了 TAG/SQL 屬性過濾功能,極大程度地拓寬了用戶的使用場景。
高性能、無限拓展能力
消息隊列 RocketMQ 經受了阿里核心電商歷年雙十一洪峰的考驗,支持千萬級 TPS 消息收發和億級消息堆積的能力,并且能夠為消息提供毫秒級端到端延遲保障,另外還提供分級存儲,支持海量消息的任意保存時間。
可觀測、免運維能力
消息隊列 RocketMQ 提供了一個可觀測性大盤,支持細粒度數據大盤,提供了消息全鏈路生命周期追蹤和查詢能力,對各個指標提供了相應的監控報警功能;此外,還提供了消息回溯和死信隊列功能,能夠保證用戶的消息能夠隨時回溯消費。
高 SLA 和穩定性保障
消息隊列 RocketMQ 的穩定性是我們一貫、持續、穩定投入的重要領域,提供了高可用部署和多副本寫入功能;另外也支持同城多 AZ 容災和異地多活。
產品剖面
接下來,我們會從以上的產品核心能力中挑選幾個剖面,并且結合具體的場景和實踐來做進一步的介紹。
多消息類型支持
高可用順序消息
商業版本消息隊列 RocketMQ 使用的順序消息我們稱之為高可用順序消息。在介紹高可用順序消息之前,首先簡要介紹下開源版本 RocketMQ 的順序消息。
順序消息分為兩種類型,全局順序消息和分區順序消息。
- 全局順序消息:在 RocketMQ 存儲層只會分配一個分區,也就是說全局順序 Topic 的可用性跟單一副本的可用性強相關,且不具備可擴展的能力。
 - 分區順序消息:所有消息根據 Sharding Key 進行分區。同一個分區內的消息按照嚴格的 FIFO 順序進行發布和消費。Sharding Key 是順序消息中用來區分不同分區的關鍵字段。
 
下圖是分區順序消息的應用場景,order ID 即為此時順序消息的 Sharding Key。
可以看到,無論是全局順序消息還是分區順序消息,都依賴了單一分區天然的 FIFO 特性來保證順序,因此順序性也只能在同一個分區內保證,當此分區所在的副本不可用時,順序消息并不具備重試到其他副本的能力,此時消息的順序性就難以得到保證。
為了解決這一問題,我們設計并實現了高可用順序消息。
高可用順序消息有以下幾個特點:
- 一個邏輯順序分區(PartitionGroup)下有多個物理分區。
 - 其中任意一個物理分區是可寫的,那么整個邏輯分區是可寫且有序的。
 - 我們基于 happened-before 的原則設計了一套基于分區位點的排序算法。
 - 根據該算法,消費者在消費某一邏輯分區時,會從其所屬的各個物理分區中拉取消息并進行合并排序,得出正確的消息順序流。
 
通過這樣的設計,高可用順序消息解決了下列幾點問題:
- 可用性問題:高可用順序消息將具備與普通消息一致的可用性,在某副本不可用時,可快速重試至其它副本。
 - 可擴展性問題:普通順序消息,特別是普通全局順序消息,不具備良好的擴展能力,只能固定在特定的副本中。高可用順序消息的邏輯順序分區可以將物理順序分區分散在多個副本中。
 - 熱點問題:普通順序消息根據 Key 將一類消息 Hash 至同一個分區中,熱點 Key 會導致熱點分區,高可用順序消息具備橫向擴展能力,可以為邏輯順序分區添加多個物理分區來消除熱點問題。
 - 單點問題:普通全局順序消息,僅包含單分區,極易出現單點故障,高可用順序消息可以消除全局順序消息的單點問題。
 
尤其需要注意的是熱點問題,在阿里巴巴內部某電商業務大促時,因發送到順序 Topic 的某一特定的 ShardingKey 數量過多,集群中一個副本接收到了大量該 ShardingKey 的消息,導致該副本超出其負荷上限,造成了消息的延遲和堆積,一定程度上影響了業務。在使用了高可用順序消息之后,由于其在多物理分區中的負載均衡特性,提升了集群順序消息的承載能力,從而避免了熱點問題的出現。
秒級精準定時消息
定時消息,是指客戶端當前發送但希望在未來的某個時間內收到的消息。定時消息廣泛應用于各類調度系統或者業務系統之中。比如支付訂單,產生一個支付消息,系統通常需要在一定時間后處理該消息,判斷用戶是否支付成功,然后系統做相應處理。
開源版本的 RocketMQ 只支持幾個指定的延遲級別,并不支持秒級精度的定時消息。而面向集團內和云上多樣化的需求,開源版本的定時消息并不能滿足我們的需求,因此我們推出了秒級精準定時消息。
如下圖所示,我們基于時間輪設計并實現了支持任意定時時間的秒級精準定時消息,同時滿足以下特性:
- 任意定時時間
 - 超長定時時間
 - 海量定時消息
 - 刪除定時消息
 - 高可用
 - 高性能
 
內部某用戶有這樣的場景,期望在未來的某一分鐘的 30s 時刻處理這樣一個定時請求,開源版本的定時消息并不符合其需要,而秒級精準定時消息在保證高可用、高性能的同時,滿足了其業務需求。
分布式事務消息
如下圖所示,在傳統的事務處理中,多個系統之間的交互耦合到一個事務中,造成整體的相應時間長,回滾過程復雜,從而潛在影響了系統的可用性;而 RocketMQ 提供的分布式事務功能,在保證了系統松耦合和數據最終一致性的前提下,實現了分布式事務。
消息隊列 RocketMQ 提供的事務消息處理步驟如下:
- 發送方將半事務消息發送至消息隊列 RocketMQ 版服務端。
 - 消息隊列 RocketMQ 版服務端將消息持久化成功之后,向發送方返回 Ack 確認消息已經發送成功,此時消息為半事務消息。
 - 發送方開始執行本地事務邏輯。
 - 發送方根據本地事務執行結果向服務端提交二次確認(Commit 或是 Rollback),服務端收到 Commit 狀態則將半事務消息標記為可投遞,訂閱方最終將收到該消息;服務端收到 Rollback 狀態則刪除半事務消息,訂閱方將不會接受該消息。
 
基于這樣的實現,我們通過消息實現了分布式事務特性,即本地事務的執行結果會最終反應到訂閱方是否能接收到該條消息。
消息隊列 RocketMQ 的分布式事務消息廣泛地應用于阿里巴巴核心交易鏈路中,通過分布式事務消息,實現了最小事務單元;交易系統和消息隊列之間,組成一個事務處理;下游系統(購物車、積分、其它)相互隔離,并行處理。
分級存儲
背景
隨著云上客戶的不斷增多,存儲逐漸成為 RocketMQ 運維的重要瓶頸,這包括并且不限于:
基于以上現狀,分級存儲方案應運而生。
架構
分級存儲的整體架構如下:
通過這樣的設計,我們實現了消息數據的冷熱分離。
使用場景
基于分級存儲,我們進一步拓展了用戶的使用場景:
穩定性
消息隊列 RocketMQ 的穩定性是我們一貫、持續、穩定投入的重要領域。在介紹我們在穩定性的最新工作之前,首先帶大家回顧下 RocketMQ 高可用架構的演進路線。
高可用架構演進路線
2012 年,RocketMQ 作為阿里巴巴全新一代的消息引擎問世,并隨后開源至社區,第一代 RocketMQ 高可用架構也隨之誕生。如下圖所示,第一代高可用架構采取當時流行的 Master-Slave 主從架構,寫流量經過 Master 節點同步至 Slave 節點,讀流量也經過 Master 節點并將消費記錄同步至 Slave 節點。當 Master 節點不可用時,整個副本組可讀不可寫。
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 客戶端的機制來完成。如下圖所示:
- Producer 在主不可用時,靈活快速地切換至另一個副本組。
 - Consumer 在某個副本不可用時可快速切換至同副本組另一個副本上進行消息消費。
 
可觀測性
健康大盤
我們在可觀測性方面也做了大量的工作,為用戶提供了一個消息系統的可觀測性健康數據大盤。如下圖所示,用戶能夠清晰的看到實例級別、topic 級別、group 級別的各種監控數據,能夠全方面地監控、診斷問題。
消息鏈路追蹤
另外我們還基于消息軌跡提供了消息全鏈路軌跡追蹤功能。如下圖所示,用戶能夠在控制臺上看到完整的消息生命周期、從消息的發送、存儲、到消費,整個鏈路都能被完整地記錄下來。
應用場景
客戶痛點:業務出現消費堆積的用戶需要根據消息軌跡抽樣數據,綜合分析后才能大致判斷引起問題原因,排查困難。
核心價值:提高線上運行問題排查的效率,和問題定位的準確性。直接在健康大盤上快速發現風險最高的 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 具備事件驅動的動力,從而擁抱整個事件生態。接下來我們將借助一個案例,如下圖所示,為大家展示這一功能。
創建消息隊列 RocketMQ 主題
創建目標服務
我們基于容器服務快速創建一個事件驅動的服務,計算負載 Deployment 的 yaml 如下,該服務能夠響應事件并將結果打印到標準輸出中。
前往容器服務控制臺,進入服務與路由的服務頁面,創建一個私網訪問類型的 Service,并做好端口映射。
創建事件總線 EventBridge 自定義總線
我們來到事件總線 EventBridge 控制臺,創建一個自定義總線 demo-with-k8s。
創建事件總線 EventBridge 自定義總線規則
我們為總線 demo-with-k8s 創建一個規則,并選擇 HTTP 作為事件目標,選擇專有網絡類型,選中對應的 VPC、 VSwitch 以及安全組,并指定目標URL,如下圖所示:
創建事件總線 EventBridge 事件源
我們為該自定義事件總線添加消息隊列 RocketMQ 版的自定義事件源。
發送 RocketMQ 消息
接下來我們回到消息隊列 RocketMQ 控制臺,通過控制臺的快速體驗消息生產功能發送一條內容為 hello eventbridge 的消息到對應的主題中去。
接下來我們就可以發現,這條 RocketMQ 消息,以 CloudEvent 的形式被投遞到了對應的服務中去,我們從而打通了消息到事件的鏈路。同時,基于我們上述提到的分級存儲功能,消息隊列 RocketMQ 轉變成了一個能夠源源不斷提供事件的數據倉庫,為整個事件生態提供了更加廣闊的場景。
事件驅動是未來商業組織和業務系統的重要趨勢,而消息隊列 RocketMQ 會堅定地擁抱這一趨勢,將消息融入到事件的生態中。
總結
我們選取了消息隊列 RocketMQ 的幾個產品剖面,從多消息類型、分級存儲到穩定性、可觀測性,再到面向未來的事件驅動,并結合與開源 RocketMQ 的對比,及具體應用場景的分析,為大家展示了基于消息隊列 RocketMQ 的大型分布式應用上云最佳實踐。
原文鏈接:https://developer.aliyun.com/article/799142?
版權聲明:本文內容由阿里云實名注冊用戶自發貢獻,版權歸原作者所有,阿里云開發者社區不擁有其著作權,亦不承擔相應法律責任。具體規則請查看《阿里云開發者社區用戶服務協議》和《阿里云開發者社區知識產權保護指引》。如果您發現本社區中有涉嫌抄襲的內容,填寫侵權投訴表單進行舉報,一經查實,本社區將立刻刪除涉嫌侵權內容。總結
以上是生活随笔為你收集整理的基于消息队列 RocketMQ 的大型分布式应用上云最佳实践的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 【下载】《看见新力量》第二期,带你走进数
 - 下一篇: 《Saas模式云原生数据仓库应用场景实践