基於 RocketMQ 的同城雙活架構在美菜網的挑戰與實踐

  • 2019 年 10 月 4 日
  • 筆記

本文整理自李樣兵在北京站 RocketMQ meetup分享美菜網使用 RocketMQ 過程中的一些心得和經驗,偏重於實踐。

嘉賓李樣兵,現就職於美菜網基礎服務平台組,負責 MQ ,配置中心和任務調度等基礎組件開發工作。

今天主要從三個方面進行分享:

  • 美菜網消息隊列的歷史
  • 基於 RocketMQ 我們做了那些事情
  • 同城雙活的選型和思考

美菜網消息隊列的歷史


美菜網歷史上是多套 MQ 並存,Kafka 用於大數據團隊;NSQ 和 RocketMQ 用於線上業務。

多套集群存在的問題:

1、維護和資源成本高昂:Kafka 用 Scala 語言, NSQ 用 GO 語言, RocketMQ 用 Java 語言,維護成本較高,每套 MQ 不論消息量多少,至少部署一套,資源成本較高。

2、易用性較差:三套 MQ 基本上都是開箱直接使用,二次開發比較少,業務接入不方便,使用混亂。消費者接入時,需要知道 topic 在那套集群上,使用哪種客戶端接入。

3、可靠性:比較了一下 RocketMQ 和 NSQ 內置的複製機制。NSQ 多通道之間是複製的,但是其本身是單副本的,存在消息丟失的風險。

統一集群的選型比較:

1、功能性,核心的功能每個 MQ 都有,考慮更多的是附加功能,比如延遲消息、順序消息、事務消息,還有就是消息的回溯、基於 key 的檢索。

2、可靠性, RocketMQ 就像前面幾位老師說的,有多種刷盤和同步機制,可以結合自己的需求靈活配置,美菜網用了 2 年多時間,表現一直比較穩定。

3、技術棧的匹配,公司是以 java 語言為主,php 為輔。

4、社區完備性來說, RocketMQ 社區是比較活躍的,而且支援也是比較到位。

可以通過微信、釘釘、郵件,還有像今天這樣的線下沙龍,這也是我們考慮的一個非常重要的點。

統一集群的遷移方案:

1、協議的兼容, RocketMQ TCP 協議,對 java 原生支援,僅需依賴一個 jar 就可以進行使用了, NSQ 使 http 協議。

2、業務的無感,遷移過程中,解耦生產者和消費者遷移,實現平滑的遷移。

3、消息不丟失,遷移過程中消息必然是不能丟失消息的,很容易理解。我們來看下圖,這個是我們當時遷移時的解決方案。

左邊是 Producer ,業務通過 Http 連接 NSQ ,對於生產者,實現一個 http 網關,來接收業務生產消息轉發到 RocketMQ 。對於消費者,實現一個 transfer 的工具,將消息透傳到 NSQ ,這樣對消費端是無感的,生產端完成遷移了,消費者可以逐步的往 RocketMQ 上遷移了,所以整個遷移過程還是比較順利的。

基於RocketMQ我們做了那些事情


訴求:

1、多語言支援,前面已經提到了美菜網的技術棧以 Java 語言為主,還有 php , go , python 語言等。

2、易用性,業務接入快捷,方便。

3、穩定性,保證整個平台的穩定可靠。

多語言的支援:

生產處理器,提供 HTTP 協議消息生產支援;消費處理器,消費端的網關,不斷從 RocketMQ 拉取消息,通過 http 發送到消費端client;流量調度器,根據 topic 的 SLA 做路由、流量調度。

易用性:

主要是從業務使用角度,降低業務的接入成本,提高業務接入的效率。

1、自定義 SDK ,同時定義了一個 spring 標籤庫,使用起來簡單。

2、加入了一些 trace ,指標採集功能,對消息積壓和失敗的報警。

3、消息軌跡,消息從生產到 broker ,再到消費有一個完整的可以追蹤的功能,這樣出現了問題就可以很容易的排查,防止出現生產者說發了消息,消費者說沒有收到消息的相互扯皮的問題。

4、失敗消息補發, RocketMQ 是有失敗重試機制的,失敗消息會進行 16 的失敗重試,最終到死信隊列中,不再投遞。可能業務系統出現了故障,經過較長一段時間的解決,解決之後希望消息可以重新發送。

穩定性:

1、集群隔離,我們會按照 SLA 隔離出業務集群、日誌集群、計算集群。業務集群採用的主從同步,同步落盤,計算集群採用主從非同步,非同步落盤,日誌集群就是單主結構

2、完善故障預案

  • 節點故障,快速下線,一鍵擴容。
  • 主節點掛掉,從節點提升為主節點,主節點改為只讀。

3、完善監控報警機制

  • 生產延遲, TPS , TP99 多維度指標數據

同城雙活的選型和思考


背景:

1、保證數據可靠性,如果所有數據都在一個機房,一旦這個機房出了問題,數據有丟失的風險。

2、機房的擴容,單機房畢竟容量有限,多個機房可以分擔流量。

方案選型:

1、同城冷備,備用一套服務存在但不對外提供服務,當另一套服務有問題時進行切換,但是真的出了問題,我們是否敢切流量呢?

2、同城雙活,平時就是雙機房對外提供服務,出問題的時候切掉故障機房,真正實現容災的目的。

幾點訴求:

1、機房就近,生產者在a機房,生產後的數據也在 a 機房的 broker ;消費者在b機房,消費的消息也來自 b 機房 broker 。

2、應用平滑遷移,支援按 topic ,應用逐步遷移。

3、故障的快速切換。

幾個關鍵點:

就近識別演算法:

1、 IP 段的方式,不同的 IP 段表示不同的機房,該方案對公司網路要求較高,公司網路調整,也需要修改修改演算法,升級客戶端。

2、協議層增加機房標識,在生產和消費的 client 通訊的時候都添加上所在機房標識,改動成本較高。

3、 broker 名字增加機房標識,客戶端 clientID 增加機房標識,該方案改動成本較低,對 MQ 核心功能無入侵。

數據複製:

實現主-從-從結構,基於 slave 非同步複製,減輕 master 節點的壓力。

故障預案:

機房或鏈路出現問題時。需要關閉一層機房的寫許可權。

機房接入層故障,無影響。

我們接下來要做的事情

1、大規模集群化的運維。目前的情況下,當大規模集群需要運維的時候是很棘手的,如果實現真正的無人值守的就會好很多。

2、按 SLA 進行自動 topic 路由調整。目前這個需要我們和業務方去提前溝通確認好,人工來調整,未來期望可以自動調整。

本文作者:

李樣兵, 2012 年研究生畢業, 2016 年加入美菜,現就職於美菜網基礎服務平台組,負責 MQ ,配置中心和任務調度等基礎組件開發工作。

整理人:王磊

本文縮略圖:icon by 訫諾-好逑