中間件技術及雙十一實踐·消息中間件篇 消息中間件——分佈式消息的廣播員

綜述

消息中間件是一種由消息傳送機制或消息隊列模式組成的最典型的中間件技術。通過消息中間件,應用程序或組件之間可以進行可靠的異步通訊來降低系統之間的耦合度,從而提高整個系統的可擴展性和可用性。

3.1、Notify

Notify是淘寶自主研發的一套消息服務引擎,是支撐雙11最爲核心的系統之一,在淘寶和支付寶的核心交易場景中都有大量使用。消息系統的核心作用就是三點:解耦,異步和並行。下面讓我以一個實際的例子來說明一下解耦異步和並行分別所代表的具體意義吧:

假設我們有這麼一個應用場景,爲了完成一個用戶註冊淘寶的操作,可能需要將用戶信息寫入到用戶庫中,然後通知給紅包中心給用戶發新手紅包,然後還需要通知支付寶給用戶準備對應的支付寶賬號,進行合法性驗證,告知sns系統給用戶導入新的用戶等10步操作。
那麼針對這個場景,一個最簡單的設計方法就是串行的執行整個流程,如圖3-1所示:
圖3-1-用戶註冊流程.jpg
圖3-1-用戶註冊流程

這種方式的最大問題是,隨着後端流程越來越多,每步流程都需要額外的耗費很多時間,從而會導致用戶更長的等待延遲。自然的,我們可以採用並行的方式來完成業務,能夠極大的減少延遲,如圖3-2所示。

圖3-2-用戶註冊流程-並行方式
圖3-2-用戶註冊流程-並行方式

但並行以後又會有一個新的問題出現了,在用戶註冊這一步,系統並行的發起了4個請求,那麼這四個請求中,如果通知SNS這一步需要的時間很長,比如需要10秒鐘的話,那麼就算是發新手包,準備支付寶賬號,進行合法性驗證這幾個步驟的速度再快,用戶也仍然需要等待10秒以後才能完成用戶註冊過程。因爲只有當所有的後續操作全部完成的時候,用戶的註冊過程纔算真正的“完成”了。用戶的信息狀態纔是完整的。而如果這時候發生了更嚴重的事故,比如發新手紅包的所有服務器因爲業務邏輯bug導致down機,那麼因爲用戶的註冊過程還沒有完全完成,業務流程也就是失敗的了。這樣明顯是不符合實際的需要的,隨着下游步驟的逐漸增多,那麼用戶等待的時間就會越來越長,並且更加嚴重的是,隨着下游系統越來越多,整個系統出錯的概率也就越來越大。

通過業務分析我們能夠得知,用戶的實際的核心流程其實只有一個,就是用戶註冊。而後續的準備支付寶,通知sns等操作雖然必須要完成,但卻是不需要讓用戶等待的。
這種模式有個專業的名詞,就叫最終一致。爲了達到最終一致,我們引入了MQ系統。業務流程如下:

主流程如圖3-3所示:

圖3-3-用戶註冊流程-引入MQ系統-主流程
圖3-3-用戶註冊流程-引入MQ系統-主流程

異步流程如圖3-4所示:

圖3-4-用戶註冊流程-引入MQ系統-異步流程
圖3-4-用戶註冊流程-引入MQ系統-異步流程

核心原理

Notify在設計思路上與傳統的MQ有一定的不同,他的核心設計理念是
1. 爲了消息堆積而設計系統
2. 無單點,可自由擴展的設計

下面就請隨我一起,進入到我們的消息系統內部來看看他設計的核心原理

  • 爲了消息堆積而設計系統在市面上的大部分MQ產品,大部分的核心場景就是點對點的消息傳輸通道,然後非常激進的使用內存來提升整體的系統性能,這樣做雖然標稱的tps都能達到很高,但這種設計的思路是很難符合大規模分佈式場景的實際需要的。
    在實際的分佈式場景中,這樣的系統會存在着較大的應用場景瓶頸,在後端有大量消費者的前提下,消費者出現問題是個非常常見的情況,而消息系統則必須能夠在後端消費不穩定的情況下,仍然能夠保證用戶寫入的正常並且TPS不降,是個非常考驗消息系統能力的實際場景。
    也因爲如此,在Notify的整體設計中,我們最優先考慮的就是消息堆積問題,在目前的設計中我們使用了持久化磁盤的方式,在每次用戶發消息到Notify的時候都將消息先落盤,然後再異步的進行消息投遞,而沒有采用激進的使用內存的方案來加快投遞速度。
    這種方式,雖然系統性能在峯值時比目前市面的MQ效率要差一些,但是作爲整個業務邏輯的核心單元,穩定,安全可靠是系統的核心訴求。
  • 無單點,可自由擴展的設計

圖3-5-Notify系統組成結構
圖3-5-Notify系統組成結構

圖3-5展示了組成Notify整個生態體系的有五個核心的部分。

  • 發送消息的集羣這主要是業務方的機器,這些APP的機器上是沒有任何狀態信息的,可以隨着用戶請求量的增加而隨時增加或減少業務發送方的機器數量,從而擴大或縮小集羣能力。
  • 配置服務器集羣(Config server)這個集羣的主要目的是動態的感知應用集羣,消息集羣機器上線與下線的過程,並及時廣播給其他集羣。如當業務接受消息的機器下線時,config server會感知到機器下線,從而將該機器從目標用戶組內踢出,並通知給notify server,notify server 在獲取通知後,就可以將已經下線的機器從自己的投遞目標列表中刪除,這樣就可以實現機器的自動上下線擴容了。
  • 消息服務器(Notify Server)消息服務器,也就是真正承載消息發送與消息接收的服務器,也是一個集羣,應用發送消息時可以隨機選擇一臺機器進行消息發送,任意一臺server 掛掉,系統都可以正常運行。當需要增加處理能力時,只需要簡單地增加notify Server就可以了
  • 存儲(Storage)Notify的存儲集羣有多種不同的實現方式,以滿足不同應用的實際存儲需求。針對消息安全性要求高的應用,我們會選擇使用多份落盤的方式存儲消息數據,而對於要求吞吐量而不要求消息安全的場景,我們則可以使用內存存儲模型的存儲。自然的,所有存儲也被設計成了隨機無狀態寫入存儲模型以保障可以自由擴展。
  • 消息接收集羣業務方用於處理消息的服務器組,上下線機器時候也能夠動態的由config server 感知機器上下線的時機,從而可以實現機器自動擴展。

3.2、Notify雙11準備與優化

在雙11的整個準備過程中,Notify都承載了非常巨大的壓力,因爲我們的核心假定就是後端系統一定會掛,而我們需要能夠承載整個交易高峯內的所有消息都會堆積在數據庫內的實際場景。
在多次壓測中,我們的系統表現還是非常穩定的,以60w/s的寫入量堆積4.5億消息的時候,整個系統表現非常淡定可靠。在真正的大促到來時,我們的後端系統響應效率好於預期,所以我們很輕鬆的就滿足了用戶所有消息投遞請求,比較好的滿足了用戶的實際需要。

3.3、MetaQ

METAQ是一款完全的隊列模型消息中間件,服務器使用Java語言編寫,可在多種軟硬件平臺上部署。客戶端支持Java、C++編程語言,已於2012年3月對外開源,開源地址是:http://metaq.taobao.org/。MetaQ大約經歷了下面3個階段

  • 在2011年1月份發佈了MetaQ 1.0版本,從Apache Kafka衍生而來,在內部主要用於日誌傳輸。
  • 在2012年9月份發佈了MetaQ 2.0版本,解決了分區數受限問題,在數據庫binlog同步方面得到了廣泛的應用。
  • 在2013年7月份發佈了MetaQ 3.0版本,MetaQ開始廣泛應用於訂單處理,cache同步、流計算、IM實時消息、binlog同步等領域。MetaQ3.0版本已經開源,參見這裏

綜上,MetaQ借鑑了Kafka的思想,並結合互聯網應用場景對性能的要求,對數據的存儲結構進行了全新設計。在功能層面,增加了更適合大型互聯網特色的功能點。

MetaQ簡介

圖3-6-MetaQ整體結構

如圖3-6所示,MetaQ對外提供的是一個隊列服務,內部實現也是完全的隊列模型,這裏的隊列是持久化的磁盤隊列,具有非常高的可靠性,並且充分利用了操作系統cache來提高性能。

  • 是一個隊列模型的消息中間件,具有高性能、高可靠、高實時、分佈式特點。
  • Producer、Consumer、隊列都可以分佈式。
  • Producer向一些隊列輪流發送消息,隊列集合稱爲Topic,Consumer如果做廣播消費,則一個consumer實例消費這個Topic對應的所有隊列,如果做集羣消費,則多個Consumer實例平均消費這個topic對應的隊列集合。
  • 能夠保證嚴格的消息順序
  • 提供豐富的消息拉取模式
  • 高效的訂閱者水平擴展能力
  • 實時的消息訂閱機制
  • 億級消息堆積能力

MetaQ存儲結構

MetaQ的存儲結構是根據阿里大規模互聯網應用需求,完全重新設計的一套存儲結構,使用這套存儲結構可以支持上萬的隊列模型,並且可以支持消息查詢、分佈式事務、定時隊列等功能,如圖3-7所示。

圖3-7-MetaQ存儲體系
圖3-7-MetaQ存儲體系

MetaQ單機上萬隊列

MetaQ內部大部分功能都靠隊列來驅動,那麼必須支持足夠多的隊列,才能更好的滿足業務需求,如圖所示,MetaQ可以在單機支持上萬隊列,這裏的隊列全部爲持久化磁盤方式,從而對IO性能提出了挑戰。MetaQ是這樣解決的

  • Message全部寫入到一個獨立的隊列,完全的順序寫
  • Message在文件的位置信息寫入到另外的文件,串行方式寫。

通過以上方式,既做到數據可靠,又可以支持更多的隊列,如圖3-8所示。

圖3-8-MetaQ單機上萬隊列
圖3-8-MetaQ單機上萬隊列

MetaQ與Notify區別

  • Notify側重於交易消息,分佈式事務消息方面。
  • MetaQ側重於順序消息場景,例如binlog同步。以及主動拉消息場景,例如流計算等。

3.4、MetaQ雙11準備與優化

  • Notify 交易消息轉 MetaQ 方案改進
    MetaQ 交易集羣主要是 Notify 交易消息的一個鏡像,舊有的方案是通過 Notify-Client 訂閱 Notify 交易消息,然後再轉投到 MetaQ 集羣,這個方案的缺點:1. 通過消息訂閱的方式給 Notify 集羣帶來比較大的壓力 2. 一旦 MetaQ 集羣處理不及時會給 Notify 造成消息的堆積,從而帶來連鎖不良效應。新的方案則是從Notify DB直接拉取binlog到MetaQ,它帶來的優勢: 1. 解放 NotifyServer 集羣的壓力;2. 通過 binlog 批量處理可以提升系統的吞吐量。
  • 交易集羣低延遲優化
    天貓直播間,旨在通過實時獲取活動當天的交易數據,通過實時流計算的方式,及時、準確的展示各業務數據。它的特點就是數據全而準確、實時性要求較高。而在全鏈路壓測過程中發現從 Notify Mysql binlog 獲取數據時,出現較大的延遲,最嚴重的延遲高達4h+,這顯然是不合系統需求的。基於這些問題,我們在 Notify Mysql 端做了很多的優化:
    1. Mysql 數據庫實例擴容,從而提高集羣的整體吞吐量;
    2. 對 binlog 的存放位置進行優化,將數據存儲以及 binlog 存儲進行分離,從而發揮 DB 的最大寫性能;
    3. 由於 MySQL 的 binlog 操作存在鎖操作,優化了 MySQL 生成 binlog 的配置,保證了拉 binlog 無延時。
  • 針對不同集羣運行參數調優
    根據業務的特點,對不同集羣的運行參數調優,如批量拉取大小,刷盤方式,數據有效期等等;同時對io調度、虛擬內存等參數進行調優,以提供更爲高效的堆積。
  • 監控與實時告警
    任何一個值得信賴的系統,最低限度是需要做到及時發現並處理異常,在第一時間排除故障發生的可能,從而提高產品的可用性。在雙十一活動之前,我們實現了由 MetaQ 系統內部,根據集羣狀態,各消息的業務數據指標進行監控統計並主動告警,同時還能通過 Diamond 做到動態調整,從而提高監控的及時性以及靈活性。

回顧雙十一活動當日,淘寶消息寫入總量112億,消息投遞總量220億,支付寶消息寫入總量24億,消息投遞總量24億。其中實時直播間集羣消息寫入峯值爲13.1w,消息投遞峯值爲27.8w。

從總體上看,我們的前期準備還是比較充分的,MetaQ 各集羣在高峯期表現穩定,全天表現很平穩,個別訂閱組對消息進行重溯,部分消息有少量的堆積,但都沒有對系統造成影響,效果還是非常好的。75%的交易在聚石塔上完成,實時直播間交易統計延遲在1s左右,加減庫存做到零超賣。

小結

目前分佈式消息中間件產品已經服務於整個集團,支持了阿里集團各個公司的500多個業務應用系統。每日處理海量消息超350億次,保證所有交易數據高可靠,高性能,分佈式事務處理,是中間件團隊最老牌的中間件產品之一。

系列文章:

中間件技術及雙十一實踐之中間件總體介紹http://jm-blog.aliapp.com/?p=3359

中間件技術及雙十一實踐之軟負載篇http://jm-blog.aliapp.com/?p=3450

中間件技術及雙十一實踐·服務框架篇http://jm-blog.aliapp.com/?p=3462

中間件技術及雙十一實踐·EagleEye篇http://jm-blog.aliapp.com/?p=3465

《中間件技術及雙十一實踐·消息中間件篇》http://jm-blog.aliapp.com/?p=3483

如果覺得內容還行,請分享給更多的人...

轉發:中間件技術及雙十一實踐之中間件總體介紹

轉發:中間件技術及雙十一實踐之軟負載篇

轉發:中間件技術及雙十一實踐·服務框架篇

轉發:中間件技術及雙十一實踐·EagleEye篇

轉發:中間件技術及雙十一實踐·消息中間件篇

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