RocketMQ 5.0: 儲存計算分離新思路

語言: CN / TW / HK

作者 |   林清山

Apache RocketMQ 自 2012 年開源以來,因其架構簡單、業務功能豐富、具備極強的可擴充套件性等特點被廣泛採用。RocketMQ 在阿里巴巴集團內部有著數千臺的叢集規模,每天十萬億訊息流轉的規模。在阿里雲上,RocketMQ 的商業化產品也以彈性雲服務的形式為全球數萬個使用者提供企業級的訊息解決方案,被廣泛應用於網際網路、大資料、移動網際網路、物聯網等領域的業務場景,成為了業務開發的首選訊息中介軟體。 儘管訊息中介軟體 RocketMQ 在阿里巴巴和開源社群已經走過了十多個年頭,但在雲原生浩浩蕩蕩的浪潮下,我們開始對 RocketMQ 的架構有了一些新的思考。

痛點與困局

阿里巴巴有大規模實踐 RocketMQ 的生產經驗,自 RocketMQ 從 2016 年對外商業化以來,一直延續跟集團訊息中介軟體相同的架構為雲上的客戶提供全託管的訊息服務,發展至今,訊息佇列 RocketMQ 在雲上已經具備相當大的業務規模。隨著業務的發展,這套極簡的分散式架構在雲原生環境下逐漸顯露出了一些不足,比如,運維成本增加、效率降低。

集團訊息中介軟體通過儲存計算一體化的部署架構,為集團電商業務提供了高效能、低延遲、低成本的訊息服務。隨著雲的進化,雲開始變得更加彈性,網路環境更加複雜,雲原生時代對效率也有了更高的要求,我們也迎來了對雲上訊息架構進行雲原生化改造的契機。 上圖是目前RocketMQ在雲上部署的一個簡化版架構(僅包含最核心的元件),這套部署架構近年來在雲上遇到的主要痛點有以下幾點:

1.富客戶端形態

RocketMQ 的使用者需要藉助官方提供的 SDK 使用雲上的服務,這是一個比較重量級的富客戶端,提供了諸如順序消費、廣播消費、消費者負載均衡、訊息快取、訊息重試、位點管理、推拉結合、流控、診斷、故障轉移、異常節點隔離等一系列企業級特性。RocketMQ 的富客戶端極大地降低了集團內客戶的接入成本,一站式助力集團客戶構建高韌性、高效能的訊息驅動應用,但云上的富客戶端有一些不足:

  • 富客戶端跟雲原生的技術棧不匹配,比如很難跟 Service Mesh 結合,也跟 Dapr 這類新興的雲原生應用框架不相容(?),消費者物理資源耗費比較大,對 Serverless 彈性也不是很友好;
  • 多語言客戶端對齊困難,在雲上對多語言的訴求是非常強烈的,但富客戶端邏輯複雜,團隊無充足的人力保障多語言客戶端的質量,為此雲上誕生了基於 GraalVM 和 HTTP 協議的多語言 SDK,但都有其侷限性;
  • 客戶端不是完全無狀態,存在記憶體狀態,重啟的時候會觸發重平衡,導致消費抖動、延遲。這種重平衡的設計滿足了效能上的需求,但對於敏感型業務,這些抖動可以說在過去幾年貢獻了很多的工單;
  • 分割槽級別的消費粒度,客戶端負載均衡的粒度在分割槽,一個分割槽無法同時被多個消費者消費,在慢消費者場景影響非常大,無法通過擴容分擔慢消費者的壓力。

2.計算儲存一體化

Broker 是 RocketMQ 最核心的節點,承擔了服務端所有的計算和儲存邏輯,其核心能力為:

  • 計算:鑑權與簽名、商業化計量、資源管理、客戶端連線管理、消費者管控治理、客戶端 RPC 處理、訊息編解碼處理等。
  • 儲存:基於分割槽的 WAL 儲存,多型別索引(普通、定時、事務等),核心的收、發、查詢能力,多副本複製能力等。

計算儲存一體化的 Broker 具備以下優點:部署結構簡單、開源使用者可以開箱即用;部署節點少,低成本支援集團雙十一萬億級的訊息規模;資料就近處理,無中間環節,效能高,延遲低。但一體化的 Broker 在雲環境也有其侷限性:

  • 業務迭代效率低:釋出單元為 Broker,即使調整了一行計量邏輯,需要全量釋出數千臺 Broker 節點才能全網生效,導致業務創新和迭代的速度慢。
  • 穩定性風險高:計算儲存一體,但大多數業務需求都是針對計算邏輯,儲存節點相對穩定,頻繁的低價值釋出帶來了穩定性風險和運維成本;每一次因計算邏輯的修改帶來的釋出將引起快取重建、消費延遲、客戶端異常感知等問題。
  • 資源利用率低:Broker 是磁碟 IO 和記憶體密集型應用,對計算資源的消耗相對較低,但兩者一體後擴縮容也是一體的,無法將計算和儲存節點單獨做 Serverless 彈性,整體 Broker 叢集資源利用率偏低。

管控鏈路複雜:因為資料和狀態完全分散式儲存在 Broker 上,管控節點需要與每個 Broker 進行通訊,比如一個查詢操作需要命中多個 Broker 並將結果進行聚合等,導致管控鏈路的邏輯複雜。

3.客戶端與Broker直連

RocketMQ 當前的使用者通過客戶端直接與 Broker 進行通訊,鏈路是最短化的,運維簡單、延遲低,但這樣的設計無法很靈活地適配網路極其複雜的雲環境,網路上有經典網路、VPC 網路、公網,部署環境上有 OXS 區、售賣區,為客戶暴露每一個 Broker 節點帶來了運維上的負擔:

  • Broker 對客戶端不透明,客戶端感知每個 Broker 節點,Broker 的運維動作在客戶端往往有明顯的感知;
  • Broker 直接對外提供服務,需要為每個 Broker 申請 VIP,包含 Classic VIP、VPC VIP 甚至公網 IP,線上運維了數千個 VIP。每個 Broker 數個 VIP,運維代價高的同時,很長一段時間 VIP 的手動申請阻礙了RocketMQ的自動化部署。
  • 無法支援多接入點,Broker 通過 NameServer 暴露給使用者,只能暴露一個接入點,使用者一般只能在經典網路、VPC 網路以及公網接入點中三選一。

基於這個大背景,阿里雲訊息團隊對 RocketMQ 在雲上進行了雲原生架構升級專項,實踐儲存計算分離的新架構,同時引入基於gRPC 的全新多語言解決方案,來加速訊息中介軟體的雲原生化。

存算分離新思路

如何在雲上實踐存算分離,如何探索出一個適合 RocketMQ 三位一體的新架構,是 RocketMQ 進行雲原生架構升級主要考慮的點,這裡面有很多現實因素的考量:

  • RocketMQ 在阿里集團已經充分驗證了其架構優秀的特徵,是否需要適配雲的需求進行存算分離?由此帶來的延遲、額外的成本是否能覆蓋新架構帶來的新價值?
  • 阿里雲上多款訊息產品已經是存算分離的架構形態,比如訊息佇列 RabbitMQ、訊息服務 MNS,新的架構怎麼與這些產品架構進行融合?

對於第一個問題,實踐的結果已經告訴我們架構簡單的優異性,但在雲上遇到的痛點又告訴我們存算分離勢在必行,可見儲存與計算要不要分離,並不是一個非此即彼的選擇,架構上的選擇是否能都要呢?對於這個問題,我們的解法是儲存計算需要做到可分可合:

  • 「分」有兩層解釋,首先代表了模組和職責的分明,屬於計算的邏輯應該封閉在計算模組,屬於儲存的邏輯應該下成到儲存模組;第二層是計算和儲存要支援分開部署,計算完全採用無狀態的部署方式,儲存是有狀態的放式,來很好地解決在雲上多租戶場景面臨的種種問題。
  • 「合」的前提是從程式碼設計上要先分開,至於是分開部署還是合併部署完全是業務的選擇,新的架構必須要支援合併的部署形態,滿足吞吐型的業務場景。比如,阿里集團內部超大規模的訊息流場景;又比如小規模單租戶場景,不需要服務化的場景,合併部署可以快速將 RocketMQ 投產。

對於第二個問題,在阿里雲上有多個自研的不同協議標準的訊息服務,如何通過單一架構支援多產品形態至關重要,將 RocketMQ 的核心業務訊息的能力無縫複製到多個產品,放大業務價值。

總而言之,架構層面的核心理念是以儲存計算架構分離為切入點,進一步探索單一架構多產品形態,以降低訊息子產品的重複建設,最終也需要實現儲存與計算可分可合的部署形態,同時滿足雲上的運維靈活性以及開源、集團等部署簡單、高效能的需求。

1.儲存計算分離架構

RocketMQ 5.0 在架構上的第一個升級便是儲存計算分離改造,通過引入無狀態的 Proxy 叢集來承擔計算職責,原Broker 節點會逐步演化為以儲存為核心的有狀態叢集,同時會重新研發一批多語言的瘦客戶端來解決富客戶端帶來的諸多問題。

上圖是一個儲存計算分離架構的簡圖,圖中借用了 Service Mesh 關於控制和資料面的劃分思想以及 xDS 的概念來描述,架構中各個元件的職責分別為:

  • 多語言瘦客戶端,基於 gRPC 協議重新打造的一批多語言客戶端,採取 gRPC 的主要考慮其在雲原生時代的標準性、相容性以及多語言傳輸層程式碼的生成能力。
  • 導航服務(Navigation Server),通過 LB Group 暴露給客戶端,客戶端通過導航服務獲取資料面的接入點資訊(Endpoint),隨後通過計算叢集 Proxy 的 LB Group 進行訊息的收發。通過 EDS 來暴露 Proxy 的接入點資訊與通過 DNS 解析的負載均衡進行路由相比而言,可以作出更智慧與更精細的租戶及流量控制、負載均衡決策等。
  • NameServer,RocketMQ 中原有的核心元件,主要提供用於儲存的 Broker 叢集發現(CDS)、儲存單元Topic 的路由發現(RDS)等,為運維控制檯元件、使用者控制檯元件、計算叢集 Proxy 提供xDS服務。
  • Proxy,重新研發的無狀態計算叢集,資料流量的入口,提供鑑權與簽名、商業化計量、資源管理、客戶端連線管理、消費者管控治理、客戶端RPC處理、訊息編解碼處理、流量控制、多協議支援等。
  • Broker,原 Broker 模組的儲存部分獨立為新的儲存節點,專注提供極具競爭力的高效能、低延遲的儲存服務,儲存計算分離後也更易加速儲存能力的創新。原 Broker 模組的計算部分逐漸上移到 Proxy叢集當中。
  • LB Group,根據使用者的需求提供 Classic VIP、VPC VIP、Internet VIP、Single Tunnel、PrivateLink 等多樣化的接入能力。

儲存計算分離帶來的額外成本主要是延遲和成本。

關於延遲,儲存和計算節點從本地方法呼叫轉換為遠端呼叫後,無可避免地增加了延遲,一般是毫秒級別,在阿里雲上即使是跨 AZ 的網路通訊,延遲一般在 2ms 以內,這種量級的延遲增加對大多數業務來講是完全可以接受的。

  • 關於成本,存算的分開,導致網路傳輸層面,序列化和反序列化層面不可避免需要更多的 CPU 資源。但另一方面,儲存和計算一個屬於磁碟 IO、記憶體密集型,一個是 CPU 密集型,拆開後可以更好地設計規格,更好地利用碎片化資源,更容易提高資源利用率,利用雲的彈效能力,成本反而可以降低。
  • 簡而言之,在雲上環境,雲服務形態的 RocketMQ 非常適合儲存計算分離架構。

2.儲存計算合併架構

但從本質來講,儲存計算分離與就近計算和就近儲存的理念是衝突的。儲存計算一體化的架構在雲上帶來了困擾,本質還是因為雲上是一個多租戶的環境,儲存計算一體化在多租戶的場景下靈活性不夠。但很多場景往往都是小規格單租戶,其實更適合儲存計算一體化。

  • 在開源場景,開源使用者更加期望 RocketMQ 是一款開箱即用、部署簡單的訊息中介軟體,儲存計算分離架構會帶來一定的複雜度,影響開源生態的建設。
  • 在集團的場景,數千臺物理機的規模,儲存計算分離將帶來額外的機器成本。
  • 在專有云場景,很多專有云可能節點數量有限,更傾向於採用一體化的架構。

為了雲外雲內都能統一技術方案,我們更加期望的一種機構是儲存與計算可分可合的部署形態,分開部署是計算節點完全無狀態,運維迭代極其簡單,合併部署時更原架構體驗保持一致。

但無論採用什麼樣的部署架構,儲存和計算的分離都是一種良好的模組化設計方式,在程式設計層面的分開是必須要進行的。

如上圖所示,左邊是雲上一個分離部署的形態,右邊是合併部署的形態,合併部署時計算節點可以作為儲存節點的SideCar,採用網格的思想進行部署,也可以將計算和儲存揉進同一個程序進行部署。實際上,我們在實踐的過程中,通過對程式碼進行充分設計,Proxy 節點可以通過構造器構造出「Local」和「Cluster」部署兩種形態,分別對應合併部署和分離部署的兩種架構形態。

3.單一架構多產品形態

《雲原生時代訊息中介軟體的演進路線》一文中提到,阿里雲訊息團隊目前有業界最豐富的訊息產品矩陣,包括訊息佇列 RocketMQ、訊息佇列 Kafka、微訊息佇列 MQTT、訊息佇列 AMQP、訊息服務 MNS、事件匯流排EventBridge。豐富的產品矩陣是團隊多年來踐行多樣性和標準化演進路線的結果,所有的訊息子產品目前都構建在RocketMQ 儲存核心之上,非常具備統一架構的前提。

通過單一的儲存計算分離架構,支援多產品的業務形態,是雲原生訊息探索的一個重要方向。這種單一架構多產品形態會帶來諸多好處,比如計算節點共建,通過模型抽象支援多業務模型,多通訊協議,釋放重複建設的人力。通過儲存節點並池,各產品打通內部儲存節點,形成資源池合併,統一運維和管控,有助於降低成本、提高效率,加速儲存創新,孵化訊息中臺。

如上圖所示,單一架構多產品形態的核心先統一儲存和計算,並進一步統一管控和運維,真正做到一套架構支撐多個雲產品。

  • 儲存叢集足夠抽象,滿足通用的訊息存取需求。
  • 計算叢集多合一,足夠的模組化,可插拔,滿足多產品部署帶來不同許可權體系、不同協議、不同抽象模型等的需求。

總結

目前,阿里雲訊息佇列 RocketMQ 實踐儲存計算徹底分離的架構還處於第一個過渡階段,未來的路還很長,我們會投入至少 1 年的時間在公有云環境全面落地儲存計算分離架構,讓訊息服務更彈性、更雲原生,讓團隊提高效率,加速業務創新。我們期望新的架構能穩定服務於未來至少 5 年的業務增長,同時,存算可分可合的部署架構也能夠非常好地支撐不同規模開源使用者的個性化需求,讓 Apache RocketMQ 開源社群能夠整體收益於存算計算可分可合架構的新形態。