騰訊雲分佈式高可靠消息隊列CMQ架構最佳實踐

極牛技術實踐分享活動算法

極牛技術實踐分享系列活動是極牛聯合頂級VC、技術專家,爲企業、技術人提供的一種系統的線上技術分享活動。數據庫

每期不一樣的技術主題,和行業專家深度探討,專一解決技術實踐難點,推進技術創新,每兩週的週三20點正式開課。歡迎各個機構、企業、行業專家、技術人報名參加。後端

嘉賓介紹緩存

張 浩 騰訊雲產品經理性能優化

負責騰訊雲消息隊列、彈性塊存儲、負載均衡器等多款iaas層產品的產品規劃、迭代,性能體驗優化等 。微信

閆二輝 騰訊雲資深存儲架構師網絡

在大規模存儲、PaaS、虛擬化領域有長期深厚積累。目前主要從事互聯網中間件的設計研發相關工做。架構

周維躍 騰訊雲資深研發工程師併發

負責騰訊雲IaaS層虛擬化資源調度運營系統的設計研發。負載均衡

目錄

消息隊列的使用場景、價值

CMQ底層架構剖析

CMQ對比開源rabbitMQ壓測

CMQ案例最佳實踐

01|消息隊列的使用場景

消息的收發解耦:發送方和接收方不須要了解彼此,甚至不須要知道對方的存在;

屏蔽不一樣平臺之間的差別:不一樣平臺之間經過消息來實現交互,僅僅關心消息的發送和讀取;

削峯填谷,提升系統應對突發能力:發送消息端永遠不會堵塞,突發消息緩存在CMQ SERVER 端,消費者按照實際能力讀取消息;

一次生產屢次消費:一條消息能夠被多鍾類型消費者訂閱,生產着僅需生產一次便可;

跨IDC/WAN傳輸:CMQ支持消息在不一樣IDC、城市進行生產、消費,自動就近接入,對業務透明;

02|CMQ底層架構剖析

在分佈式大行其道的今天,咱們在系統內部、平臺之間普遍運用消息中間件進行數據交換及解耦。CMQ是騰訊雲內部自研基於的高可靠、強一致、可擴展分佈式消息隊列,在騰訊內部包括微信手機QQ業務紅包、騰訊話費充值、廣告訂單等都有普遍使用。目前已上線騰訊雲對外開放,本文對CMQ 核心技術原理進行分享介紹。

按照使用場景能夠將消息中間件粗略分爲:高可靠和高性能兩大類。CMQ主要適用於金融、交易、訂單等對可靠性、可用性有較高要求的業務場景。

如圖1以騰訊充值系統爲例,該充值系統經過CMQ 對交易模塊、發貨部分、結算系統進行異步解耦、削峯填谷,一方面大大下降了模塊間耦合度,另外一方面減輕了大量突發請求對後端系統的衝擊。在月初充值該系統一天通過CMQ轉發的消息超過十億條,每秒峯值超過10w,最高時有數億條消息經過CMQ的堆積能力緩衝了對後端消費模塊的壓力。

clipboard.png

圖1-某充值系統結構

CMQ總體結構如圖2所示,本文重點介紹後端broker set實現原理。一般狀況下一個set由3個節點組成,經過多副本保證消息的可靠性、多節點提升系統可用性。固然,能夠根據業務的實際需求經過增長set內節點個數來進一步提升可靠性和可用性,CMQ set 內部結構如圖3所示。

clipboard.png

圖2-CMQ總體架構圖

clipboard.png

圖3-brokerset 內部結構圖

下面分別中數據高可靠、強一致,系統可用性,可擴展、消息全路徑追蹤方面分別介紹。

高可靠保證

在可靠性保證方面主要包括如下三方面:生產可靠、存儲(堆積)可靠、消費可靠:

生產可靠

如上圖3所示,客戶端生產的消息在set 中超過半數的broker 刷盤成功後會返回確認消息告知生產消息成功。若是在必定時間以內客戶端沒有收到確認信息須要重試來確保消息發送成功。

可靠生產帶來的一個問題就是消息的重複,在網絡異常等狀況下極可能CMQ broker已經存儲消息成功只是確認包在網絡上丟失了,這樣客戶端重試生產後,在broker上存在兩條重複的消息。考慮到消息去重開銷較大,目前消息的冪等性須要業務邏輯來保證。

存儲可靠

CMQSET中一個節點爲leader 其餘節點爲follower,leader 負責全部消息的生產消費。當生產消息到達leader 節點後,經過raft 一致性模塊將請求順序寫raft log 並同步刷盤,同時將構造好的raft log 按順序經過網絡發送到其餘follower節點,follower節點同步刷盤並返回成功。當leader 收到過半數的節點同步成功信息後將此條請求提交到mq 處理狀態機,由mq 狀態機將請求應用到相應queue。大體邏輯圖4所示。

clipboard.png

圖4-數據存儲原理示意圖

因而可知,對於返回客戶端成功的消息至少是分別在兩個節點磁盤上存儲成功的,這就將磁盤故障引發的數據丟失大大下降。另外數據在磁盤上存儲時會將檢驗結果一同記下來,消費者在消費數據以前CMQ broker 會進行比較,確保消息是完整有效的。

消費可靠

消費者拉取消息時會指定當前消息的隱藏時間,在隱藏時間內消費者比較顯式的對消息進行確認刪除,若是超過隱藏時間沒有主動刪除,此條消息將從新對外可見,能夠繼續消費。

顯式確認刪除消息是爲了防止消息在投遞、處理過程當中異常而致使的消息丟失。

對於消息的確認信息 CMQ broker的處理邏輯和生產消息過程相似,也是一個寫入的過程,不一樣的是此時寫入的數據的內容是msgid 和消息狀態。

強一致實現

假如一個set中有3個節點(A, B, C),A爲leader,B C 是follower。如上圖所示,對於返回客戶端成功的請求數據在CMQ 中至少在兩個節點上存在,假設爲A B,此時若是leader A故障,B C 兩個follower 會自動選舉出一個新leader,CMQ 使用的raft 算法能夠保證這個leader 必定是擁有最全量log 信息中的一個,在此一定是B。此時B繼續對外服務,B 和A 擁有相同的已經返回確認給用戶的全量數據視圖,數據是強一致的。

對於A 和 B C 所在的網絡發生分區的狀況(如圖5),因爲leader A得不到set 中過半節點的回覆因此不能處理請求,B C在選舉超時後會選舉出一個新的leader ,CMQ的接入層會自動進行切換。Raft 算法保證新leader 一樣具備完成的數據視圖。

clipboard.png

可用性保證

clipboard.png

如上文所述,master 負責全部消息的生產消費,當master 故障時SET中其餘follower節點會自動選舉出一個新leader,客戶端請求會自動重定向到leader節點,RTO和配置的選舉超時時間有關,目前是在5s左右。大體過程如上圖6所示,具體選舉算法請參考raft 論文。

CMQ單個set 在CAP理論中優先保證了CP,當SET中過半數節點都正常工做時,才能進行消息的生產消費。對於SET多個節點同時故障的不可用狀況,CMQ強大的監控調度能力可以快速對queue進行調度遷移恢復服務,將不可用時間降到最低。

橫向擴展,無限堆積

clipboard.png

圖7橫向擴展

上文中SET的概念對用戶來講是透明無感知的,CMQ controller server 根據set的負載狀況實時對queue進行調度搬遷。若是某個queue的請求量超過當前set的服務閾值,controller server 能夠將queue 路由分佈到多個set 上來提升併發量,對於須要海量堆積的服務來講能夠經過路由調度來提高堆積上限,理論上能夠達到無限堆積。

目前CMQ只能保證特定狀況下消息的嚴格有序,例如須要保證單個生產進程、單個消費進程,或者queue的消費窗口設定爲1等條件。

全路徑消息trace

CMQ系統中,一條消息的完整路徑包含生產者、broker、消費者三個角色,每一個角色處理消息的過程當中都會在trace 路徑中增長相關的信息,將這些信息匯聚便可獲取任意一條消息的狀態和當前通過的完整路徑,從而爲生產環境中的問題排查提供強有力的數據支持。大大下降了業務定位問題的難度。

小結

CMQ是基於raft 算法來保證數據高可靠、強一致的分佈式消息隊列,主要服務於訂單、交易類業務場景。消息的冪等性需業務側來保證,在特定狀況下能夠保證消息嚴格有序。

對於更側重高性能、高吞吐量業務需求,騰訊雲由另一個消息引擎來提供服務,在協議上同時兼容kafka,很好的知足了大數據場景,具體原理請留意後續文章介紹。

03|CMQ對比開源rabbitMQ壓測

RabbitMQ 是具備表明性的開源消息中間件,當前較多地應用於企業系統內,用於對數據一致性、穩定性和可靠性要求較高的場景中。

CMQ也是強調高可靠的消息傳遞,那騰訊雲的CMQ,對比rabbitMQ有哪些優點?

功能升級

除了生產、消費確認機制,CMQ還提供了消費回溯功能。

用戶指定CMQ保存生產消息必定天數,隨後將消費回溯到該時間段內某一時間點,從該點開始從新消費。在用戶業務邏輯異常時,以時間爲起點的消息重放功能對業務恢復很是有幫助。

性能優化

網絡IO:CMQ可以批量生產/消費消息,RabbitMQ則不支持批量生產。在大量小消息場景中,CMQ具備更少的請求數和更低的平均延遲。

文件IO:CMQ生產/消費消息是順序寫單個文件,並週期落盤存儲,充分利用文件系統緩存。RabbitMQ持久化消息先入內存隊列進行狀態轉換,而後寫日誌緩存,最後寫消息文件和索引文件(索引文件爲順序寫、消息文件爲隨機寫),涉及三次IO操做,性能較差。

CPU:RabbitMQ的日誌緩存和狀態轉換運算較複雜,大量耗用CPU。

可用性提高

CMQ和RabbitMQ都可以使用多臺機器進行熱備,提升可用性。CMQ基於Raft算法實現,簡單易維護。RabbitMQ使用自創的GM算法(Guaranteed Multicast),學習難度高。

clipboard.png

Raft協議中,Log複製只要大多數節點向Leader返回成功,Leader就能夠應用該請求,向客戶端返回成功。

clipboard.png

GM可靠多播將集羣中全部節點組成一個環。Log複製依次從Leader向後繼節點傳播,當Leader再次收到該請求時,發出確認消息在環中傳播,直至Leader再次收到該確認消息,代表Log在環中全部節點同步完成。

GM算法要求Log在集羣全部節點同步以後才能向客戶端返回成功;Raft算法則只要求大多數節點同步完成。Raft算法在同步路徑上比GM算法減小了一半的等待時間。

壓測結果

經內部嚴格壓測,在同等網絡、CPU內存環境下,CMQ在保證可靠傳遞的前提下,QPS表現是rabbitMQ的4倍以上。

04|CMQ15年微信春晚紅包案例

clipboard.png

春晚紅包活動涉及四個大型系統的聯動,包括微信、微信支付、紅包系統和財付通系統。如下簡單介紹各個系統:

紅包系統:我的紅包的發、搶、拆和列表查看;

財付通系統:包括支付訂單、異步入帳流水的高性能存儲,用戶餘額和帳單的實時展現;

微信接入:確保微信用戶公網接入的質量;

微信支付:在線交易的入口。

相似紅包系統的分佈式事務是關注的熱點。舉一個典型的例子,「用戶A給用戶B發了10元的紅包」,有如下步驟:

從A賬號中把餘額讀出來

對A賬號作減法操做(減10元)

把結果寫回A賬號中(一次確認)

從B賬號中把餘額讀出來

拆開A發送給B的紅包,讀出數值

對B賬號作加法操做(加10元)

把結果寫到B賬號中

爲了保證數據的一致性,上述步驟只有兩種結果:都成功完成或者都不成功執行回滾。並且這個操做的過程當中,對A、B賬號還需引入分佈式鎖機制來避免髒數據的問題。在微信紅包這個龐大的分佈式集羣內,事情將變的異常複雜。

微信紅包系統引入了騰訊雲 CMQ 以免分佈式事務增長對系統的開銷。一樣A用戶給B用戶發10元紅包的場景,下面介紹引入CMQ 後的新策略。

在上述案例中的第七步,B 用戶拆開了紅包,紅包裏有 10 塊錢。在作最後的入帳操做時因爲當天併發壓力大,常出現入帳失敗的狀況。

紅包團隊把入賬失敗的請求,所有轉入CMQ。當B用戶更新帳戶餘額失敗時,手機客戶端顯示等待狀態。隨後入帳系統將不斷從 CMQ 從新拉取重試此更新操做。CMQ 保證了這 10 元的入帳消息永遠不丟,直至它被取出。

在除夕當天,用戶紅包的發、拆、入帳等動做,轉化爲了十億級別的海量請求。若使用傳統的事務方式,會放大併發壓力使系統崩潰。

CMQ消息隊列保證了紅包消息的可靠存儲、傳遞,實時寫三份保證數據不丟。資金入帳失敗時,入帳系統可異步的屢次重試,從CMQ拉數據,直到成功,起削峯填谷的做用。避免失敗回滾和頻繁輪詢數據庫等傳統方式的弊端。

Q&A

Q1:創業公司怎麼選擇消息隊列?

A1:開源的消息隊列有不少,實現機制複雜,運維成本也很高,對於創業企業來講,選擇雲服務商提供的消息隊列無疑是最省事的,按需使用,成本很是低。

Q2:CMQ生產的消息,若是未被消費保存多久?

A2:消息在隊列中最長的存活時間,從發送到該隊列開始通過此參數指定的時間後,不論消息是否被取出過都將被刪除;單位爲秒,有效值範圍60-1296000秒,也即1分鐘到15天。

Q3:相比kafka有什麼優點?

A3:跟kafka相比,各有側重點,kafka更強調吞吐性能。CMQ強調是可靠傳遞,不丟。 CMQ的Kafka版本也即將推出,敬請期待。

Q4:CMQ消費方式是push仍是pull?仍是二者結合?

A4:當前queue的模式咱們採起的是pull的方式。後續的topic的模式會有push,能夠支持push到http端,短信,郵件,和queue。

Q5:哪些隊列支持pubsub?

A5: 其實CMQ支持兩種產品形態:queue和topic, 對於queue來講沒有pubsub功能,topic有pubsub的能力也能把topic和queue串聯起來使用,queue能夠做爲topic其中的一個sub方。

此分享由騰訊的張浩在極牛線上技術分享羣裏所分享,有意加入的技術朋友,請在極牛公衆號(ji-niu)裏回覆「技術分享」。

相關文章
相關標籤/搜索