支持 Kafka 和 RocketMQ 等消息引擎,滴滴開源分佈式消息中間件DDMQ

滴滴出行消息隊列團隊近日開源了其內部廣泛使用的分佈式消息中間件產品 DDMQ,這是一款致力於提供低延遲、高併發、高可用、高可靠消息服務的企業級消息隊列產品。 DDMQ已經在滴滴內部穩定運行了兩年多時間,支撐了網約車、小桔車服、地圖、金融、智能駕駛、智慧交通、外賣等業務的穩定運行。日消息流水達到千億級別,整體服務可用性超過5個9。本文將從從產品特性、適用場景和架構設計等方面對 DDMQ 進行較爲詳細的介紹。

產品特性

DDMQ 具有如下的優秀特性:

  • 低延遲高吞吐:毫秒級延遲,單機百萬條消息吞吐。

  • 豐富的消息類型:具備實時消息、延時消息和分佈式事務消息。

  • 海量消息存儲,支持消息回溯消費:支持 RocketMQ 和 Kafka 作爲實時消息的存儲引擎,使用RocksDB 作爲延時消息的存儲引擎。

  • 秒級延時消息:支持單條消息設置精確到秒級的延遲時間,提供普通延時消息和循環延時消息。

  • 多語言客戶端,提供了主流開發語言SDK,包括PHP, Java, Go, C/C++, Python,在API 上保持着最易使用的 High Level 形式。

  • 多種消費方式:支持通過 Thrift RPC拉取、HTTP 推送和第三方存儲直寫的方式消費消息。

  • 支持靈活的消息過濾和轉換功能:通過使用 Groovy 腳本在服務端進行消息體的轉換和過濾,能做有效減少客戶端和服務器的數據傳輸量,減輕客戶端處理消息的負載。

  • 統一的Web控制檯:方便用戶管理Topic等資源,通過控制檯可以實現配置生產和消費的限流值、消費方式、Groovy腳本、啓停消費、重置消費進度等功能。

  • 完善的監控配套:提供模塊的健康檢查和消息堆積告警功能。

適用場景

消息隊列作爲構建現代分佈式應用所必備的基礎設施,有着廣泛的應用場景。

  • 削峯填谷

在秒殺等場景下會導致短時間流量的暴漲,下游系統會因爲缺少保護而過載甚至崩潰。DDMQ提供的海量堆積能力和消費限流能夠確保下游系統的平穩運行。

  • 異步解耦

    • 通過上下游系統的鬆耦合設計,可以保證上游系統不會因爲下游系統的宕機而不可用。確保主流程的正常穩定運行。
  • 順序消息

    • 現實中需要保證順序的場景很多,比如訂單系統中訂單創建、支付、退款等流程,均需要保證順序。 DDMQ提供的順序消費功能可以保證消息的先進先出。
  • 事務消息

    • 在微服務的場景下,通過DDMQ的事務消息能夠達到分佈式事務的最終一致性。

整體架構設計

下面這張圖描述了DDMQ 的總體架構。主要包括 Broker Cluster、Producer Proxy Cluster(以下簡稱 PProxy),Consumer Proxy Cluster(以下簡稱CProxy),SDK,Console 等模塊。

image

Broker Cluster 是DDMQ的消息存儲層。使用 RocketMQ作爲實時消息的存儲引擎(同時也支持使用Kafka),Chronos則是我們基於 RocksDB自研的延時消息存儲引擎。

PProxy 是DDMQ的生產代理服務, 內置 Thrift RPC Server,生產 SDK 通過RPC 調用將消息發送給 PProxy,然後再由PProxy負責將消息生產到具體的 Broker 中去,在 PProxy 中我們實現了生產限流、重試和消息批量生產等功能。

CProxy 是DDMQ的消費代理服務,也內置了Thrift RPC Server,當選擇SDK消費時,消費方以 pull 的方式從 CProxy 中拉取消息,由於 CProxy 中的PullBuffer提前緩存了一定數量的待消費消息,因此消費的延遲很低。如果選擇HTTP方式消費,則直接由CProxy將消息推送到業務指定的回調URL地址。在CProxy 中,我們實現了消息過濾(通過編寫Groovy腳本)、消息體轉換(Transit)、重試、消費限流、順序消費內部排序等功能。

Console是DDMQ的控制檯,用戶通過控制檯申請Topic、Group等資源。Topic等數據會持久化到MySQL並推送到 Zookeeper;PProxy和CProxy通過讀取、監聽 Zookeeper 上的Topic和Group 數據來實時控制消息的生產和消費邏輯。

DDMQ選擇Proxy+SDK的架構,主要有這幾個好處:

  • 方便多語言SDK的實現,由於滴滴內部使用的技術棧比較多,將主要邏輯放在 Proxy 上有利於降低 SDK的複雜度,讓SDK的開發速度大大加快。目前在滴滴內部支持PHP, Go , C/C++, Java, Python, Node.js等語言的SDK實現。

  • 存儲層業務無感知,由於Proxy層屏蔽了後面的RocketMQ或Kafka,使得存儲層的切換可以做到業務無感知。

  • 加快新功能迭代速度,新功能的開發都在 Proxy 層實現,降低了SDK的升級頻率。

延遲隊列的設計

在開源版本的 RocketMQ 裏提供了多種固定延遲 level 的延時消息支持,可以發送幾個固定的延時時間的延時消息,比如延時 10s, 30s…,但是這種不同延時 level 的延時消息並不能滿足滴滴內部衆多業務方的需求,我們需要的是任意時間精度的延時。因次我們基於 RocksDB 自研了延時消息隊列Chronos,以DDMQ子模塊的形式對外提供服務。

image

上面這張圖描述了 Chronos 的總體結構;簡單來說,生產 SDK 通過 PProxy 提供的 sendDelay RPC 將延時消息發送到 PProxy, 然後由 PProxy 將消息生產到 Chronos 固定的內部 topic 上(chronos_inner_xxx)。Chronos模塊再去消費 inner topic 的消息並將消息存儲到本地的 RocksDB 裏去。基於本地內置的 RocksDB 存儲引擎構造一個時間輪服務,會將到期的消息再發送給PProxy,以供業務方消費或HTTP推送給業務方。

對RocketMQ 的擴展改造 --(broker 自動主從切換)

熟悉RocketMQ的同學應該知道,目前開源版本的RocketMQ broker 是沒有主從自動切換的。如果Master掛了,那就寫不進去了。然後Slave只能提供只讀的功能。當然如果你的topic在多個主節點上都創建了,雖然不會完全寫不進去,但是對單分片順序消費的場景,還是會產生影響。所以我們就自己加了一套主從自動切換的功能。

image

結合RocketMQ現有的結構,可以採用如上結構,探活採用多個節點同時向master發送探測消息的方式,相對心跳方式,提高了準確性。具體由nameserver完成,具體流程如下:

  1. 各NameServer通過搶佔特定的臨時節點,選出Leader節點;

  2. 各NameServer向master節點發送消息,根據發送發送探活消息失敗率是否超過閾值判斷是否健康,並將狀態更新到此brokername下對應的NameServer節點中;

  3. NameServer的master發現自己跟Broker的master鏈接異常,然後檢查其他節點是否也發現master掉線,如果掉線數量超過閾值,啓動切換流程;

  4. 將broker master切換爲slave;

  5. 從原有的slave中,選出offset最大的broker,並將其切換爲master;

關於DDMQ部署安裝,可參照GitHub的說明。

GitHub 倉庫地址:https://github.com/didi/DDMQ

作者介紹

臧磊,畢業於北京大學軟件工程研究所,滴滴出行自研消息中間件 DDMQ 開源負責人,曾就職於猿題庫和今日頭條,長期專注於消息隊列等基礎設施的研發工作。目前在滴滴出行負責 DDMQ 的產品雲化和大數據生態建設等工作。

江海挺,畢業於北京大學軟件工程研究所,滴滴出行自研消息中間件 DDMQ 的產品負責人,同時對於開源的 Kafka 和 RocketMQ 等消息系統的架構設計、運行維護有着深入的理解和豐富的經驗。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章