微信後臺非同步訊息佇列的優化升級實踐分享
1、引言
MQ 非同步訊息佇列是微信後臺自研的重要元件,廣泛應用在各種業務場景中,為業務提供解耦、緩衝、非同步化等能力。本文分享了該元件2.0版本的功能特點及優化實踐,希望能為類似業務(比如移動端IM系統等)的訊息佇列設計提供一定的參考。
2、背景介紹
微信後臺給件 MQ 1.0 釋出之初,基本滿足了一般業務場景的非同步化需求,實現了單機下高效能的任務持久化和消費排程。
MQ 1.0 的基本框架如下圖所示:
可以看到,其主要分為 MQ 和 Worker 兩部分。MQ 是任務的持久化和排程框架,Worker 是任務的處理框架。
下面對各個優化點詳細講解。
3、需要實現更優的任務排程
1現狀分析
iOS訊息通知功能,是MQ元件的一個典型應用場景。微信的後臺具有多IDC分佈的特點,不同IDC與蘋果推送服務(APNs)之間的網路質量參差不齊,部分鏈路故障頻發。
由於MQ 1.0 的任務只能本機消費,網路質量的下降將直接導致 Worker 消費能力的下降,進而產生積壓,最終使訊息服務質量受損。
為此,我們提出了跨機消費模式。其目標是實現一個去中心化、自適應的彈性消費網路,以解決系統中出現的區域性積壓問題。
2任務排程是跨機消費的核心問題
下面逐一進行討論。
3拉任務還是推任務
MQ 1.0 下,MQ 可以準確觀察到本機 Worker 的負載狀態,並由其將任務推送給空閒的 Worker 進行處理。推送的方式可以將任務的處理延時做到極低。
擴充套件到跨機消費後,Worker 可以消費任意 MQ 的任務。對 MQ 而言,已經難以精確地維護全網每個 Worker 的狀態了。若繼續沿用推任務的方式,很可能會出現 Worker 接收到超過其處理能力的任務量,從而產生積壓。
4Worker 如何感知 MQ 的積壓
前面提到,系統應該在任務出現積壓時,才產生跨機消費。因此,MQ 在產生積壓時,應該要能以某種形式通知 Worker。
同時,積壓量的變化是很快的,通知的方式應該做到以下幾方面的高效:
速度:儘可能地快;
精度:儘可能少地傳送通知,減少無效通知的傳送。
為此,我們實現了廣播模式,將 MQ 產生的積壓量資訊作為一個訊息,廣播給 多個Worker。
它在實現上如何滿足高效的積壓通知要求呢?
速度:使用長連線將積壓量資訊推送到 Worker 端;
精度:通過靈活的訂閱過濾器,實現對本機、跨機、跨IDC的分級的廣播。
通過廣播模式,我們高效地解決了 MQ 積壓的感知問題。
5Worker 如何消除 MQ 的積壓
通過廣播模式,每個Worker 都可以觀察到所有它感興趣的 MQ 的積壓情況,並以此構建出整個系統的積壓分佈統計。拿到這些資訊後,Worker 如何決定拉取哪個 MQ 的任務呢?
還是回到我們的原始訴求,儘量做到本機消費。所以我們的策略是說,Worker 應該優先消除本機的積壓,當它有餘力的時候,才去幫助其它Worker。
通過分優先順序地拉取,既可在佇列系統正常時大量降低跨機消費,同時也可以在故障發生時,有效地消除區域性積壓。
6負載均衡分析
跨機消費模式,從整個系統角度來看,是完全去中心化的,任意一個 MQ 和 Worker 個體都可以獨立、自由地加入或退出系統。
在這個競爭式的消費系統裡,根據具體的部署情況、不同機型消費能力不同等因素,無法達到完全的負載均衡狀態。但在系統產生區域性過載時,則可以自適應調節,達到相對的均衡。
6小結
4、需要實現更高效的任務處理
1現狀分析
微信釋出已有6年多的時間,後臺的業務邏輯演化至今,往往是非常的複雜,我們來看一個比較極端的例子 —— 群聊批量並行化投遞。
上圖是群訊息投遞業務的簡化流程示意。隨著微信群訊息體量的高速膨脹,其帶來的成本壓力越來越大,業務同學提出了批量並行化的優化方式。簡單來說,就是將每個步驟中產生的 RPC 訪問按實際訪問機器聚合成一系列的批量操作,然後並行化執行。
通常來說,單次的批量並行化並不難寫,一般而言,業務同學可能會選擇裸寫。但如果涉及多次的批量並行化,其中還存在巢狀的話,事情就不那麼簡單了。最終程式碼將變得異常複雜,業務開發的同學苦不堪言。MQ 能否從框架上解決這類問題?
2類 MapReduce 任務處理框架
其實,深入分析群訊息投遞的優化需求,可以看到:
一次批量並行化操作本質上是一次 MapReduce 過程;
整個群訊息投遞的處理過程是多次 MapReduce 過程的串聯和並聯。
所以,為了從根本上解決這一類問題,MQ 為業務提供了類 MapReduce 任務處理框架。
該框架提供封裝了通用的 MapReduce 過程,以及併發的排程過程,同時提供併發池隔離能力,解決了併發池餓死的問題。讓業務同學可以從冗繁的程式碼中解放出來,將更多的精力投入到實際業務中。
3流式任務處理框架
除了批量並行化的需求,業務經常提到的一個需求是,任務處理時會產生一些新的任務需要加到佇列中。一般來說是走一次 RPC 來執行任務入隊。在 MQ 2.0 下,流式任務可以幫忙完成這個事情。
所謂流式任務,就是在任務處理結束時,除了返回任務結果,還可以返回一系列新的任務。這些任務通過 MQ 內部框架流轉入隊,更輕量,事務性更強。
相比常規的同步處理模型,它提供了一種輕量的邏輯非同步化模型。一個冗長的邏輯可以切分為很多小的功能塊進行串聯和複用,每一級之間都有 MQ 去充當緩衝和排程。雖然這種處理模式並不適用於所有邏輯,但作為元件功能的一部分,它提供了一種新的解決問題的能力。
4小結
MQ 2.0 提供的類 MapReduce任務處理框架和流式任務處理框架,為業務的實現提供了便利的支援。
5、需要實現更強的過載保護
1現狀分析
MQ的重要作用是充當系統中的緩衝節點,流量控制的能力是非常關鍵的。在 MQ 1.0 下,只能通過配置佇列的任務出隊速度來實現流量控制。
其問題有幾個:
配置需要人工調整,難以估算對後端的實際訪問;
後端處於過載狀態時無法自適應調整;
自己處於過載狀態時無法自適應調整。
2問題分析
從需求來看,MQ 的過載保護需求有兩個方面,一是保護自己不過載,二是保護後端不過載。
下面分別討論兩種策略。
3前向限速
基於 CPU 使用率的流控:
該限速策略很好理解,就是在 CPU 使用率過高時,降低任務處理速度,以將 CPU 資源優先用於保證佇列的快取能力。
基於任務成功率的流控:
後端模組故障時,往往會導致佇列任務出現大量的失敗和重試,這些重試的量級往往會遠超該後端模組設計的有效輸出,給故障恢復帶來很大的困難。該流控策略的通過收集任務執行的成功率資訊,評估後端的有效輸出,並通過反饋計算限制任務重試的速度。
4後向限速
MQ 實現了通用的後向限速能力,業務通過特定介面往 MQ 回傳控制量,達到速度調控的目的。
基於後端 RPC 訪問量的流控:
我們經常會遇到一些業務在處理任務時,存在不同程度的對後端的擴散訪問。僅對任務處理速度進行限制,無法準確限制對後端產生的實際呼叫量。該策略通過收集業務對後端產生的實際呼叫量,反向調節任務處理的速度。
5小結
MQ 2.0 通過分析流控需求,在前向和後向分別提供了有效的流控手段,並且為後續更精細的流控策略預留了擴充的能力,增強了過載保護的能力。
6、本文總結
微信的佇列元件,與業界其他佇列相比,其突出的特點是更貼近實際業務場景,極大地解放了業務同學的生產力。
後續,將在任務持久化容災和排程效能上,對該元件進行持續的優化。
公眾號推薦:
相關文章
- 知識分享--訊息佇列佇列
- 阿里雲訊息佇列 RocketMQ 5.0 全新升級:訊息、事件、流融合處理平臺阿里佇列MQ事件
- nsq 優秀的訊息佇列佇列
- 阿里雲訊息佇列 Kafka-訊息檢索實踐阿里佇列Kafka
- Python中執行緒的MQ訊息佇列實現以及訊息佇列的優點解析Python執行緒MQ佇列
- 訊息佇列——數十萬級訊息的消費方案佇列
- 深度 | 金融級訊息佇列的演進 — 螞蟻金服的實踐之路佇列
- Redis 應用-非同步訊息佇列與延時佇列Redis非同步佇列
- redis應用系列二:非同步訊息佇列:生產/消費模式實現及優化Redis非同步佇列模式優化
- 訊息佇列系列一:訊息佇列應用佇列
- 金融行業訊息佇列選型及實踐行業佇列
- Redis實現訊息佇列Redis佇列
- 訊息佇列佇列
- 訊息佇列(MQ)佇列MQ
- Kafka訊息佇列Kafka佇列
- RabbitMQ訊息佇列MQ佇列
- kafka 訊息佇列Kafka佇列
- POSIX訊息佇列佇列
- 訊息佇列(一)佇列
- 訊息佇列(二)佇列
- 訊息佇列二佇列
- [訊息佇列]rocketMQ佇列MQ
- [訊息佇列]RabbitMQ佇列MQ
- [Redis]訊息佇列Redis佇列
- RabbitMQ 訊息佇列之佇列模型MQ佇列模型
- Zookeeper和Curator-Framework實踐之:分散式訊息佇列Framework分散式佇列
- 雲訊息佇列 ApsaraMQ 成本治理實踐(文末附好禮)佇列MQ
- 技術分享| 訊息佇列Kafka群集部署佇列Kafka
- Redis?使用?List?實現訊息佇列的優缺點猜陂Redis佇列
- 訊息佇列中的Oracle佇列Oracle
- Laravel 的訊息佇列剖析Laravel佇列
- 阿里IM技術分享(五):閒魚億級IM訊息系統的及時性優化實踐阿里優化
- 阿里IM技術分享(四):閒魚億級IM訊息系統的可靠投遞優化實踐阿里優化
- PHP基於Redis訊息佇列實現的訊息推送的方法PHPRedis佇列
- Redis實現簡單訊息佇列Redis佇列
- 升級iOS12後微信不能提示新訊息的解決辦法iOS
- 全面理解Handler-1:理解訊息佇列,手寫訊息佇列佇列
- 分散式訊息佇列RocketMQ--事務訊息--解決分散式事務的最佳實踐分散式佇列MQ