notify-消息中間件(1)
淘寶的notify是一個非常有特色的消息中間件。它用創新地方式解決了分布式事務的問題,用相對較低的成本,實現了跨micro service的最終一致性。這種把最終一致性用application queue而不是database replication queue的方式來實現,把IT技術層面的跨業務的事務變成一個業務層面的單據傳遞的概念,非常值得推廣。
消息中間件——分布式消息的廣播員
綜述
消息中間件是一種由消息傳送機制或消息隊列模式組成的最典型的中間件技術。通過消息中間件,應用程序或組件之間可以進行可靠的異步通訊來降低系統之間的耦合度,從而提高整個系統的可擴展性和可用性。
3.1、Notify
Notify是淘寶自主研發的一套消息服務引擎,是支撐雙11最為核心的系統之一,在淘寶和支付寶的核心交易場景中都有大量使用。消息系統的核心作用就是三點:解耦,異步和并行。下面讓我以一個實際的例子來說明一下解耦異步和并行分別所代表的具體意義吧:
假設我們有這么一個應用場景,為了完成一個用戶注冊淘寶的操作,可能需要將用戶信息寫入到用戶庫中,然后通知給紅包中心給用戶發新手紅包,然后還需要通知支付寶給用戶準備對應的支付寶賬號,進行合法性驗證,告知sns系統給用戶導入新的用戶等10步操作。
那么針對這個場景,一個最簡單的設計方法就是串行的執行整個流程,如圖3-1所示:
這種方式的最大問題是,隨著后端流程越來越多,每步流程都需要額外的耗費很多時間,從而會導致用戶更長的等待延遲。自然的,我們可以采用并行的方式來完成業務,能夠極大的減少延遲,如圖3-2所示。
但并行以后又會有一個新的問題出現了,在用戶注冊這一步,系統并行的發起了4個請求,那么這四個請求中,如果通知SNS這一步需要的時間很長,比如需要10秒鐘的話,那么就算是發新手包,準備支付寶賬號,進行合法性驗證這幾個步驟的速度再快,用戶也仍然需要等待10秒以后才能完成用戶注冊過程。因為只有當所有的后續操作全部完成的時候,用戶的注冊過程才算真正的“完成”了。用戶的信息狀態才是完整的。而如果這時候發生了更嚴重的事故,比如發新手紅包的所有服務器因為業務邏輯bug導致down機,那么因為用戶的注冊過程還沒有完全完成,業務流程也就是失敗的了。這樣明顯是不符合實際的需要的,隨著下游步驟的逐漸增多,那么用戶等待的時間就會越來越長,并且更加嚴重的是,隨著下游系統越來越多,整個系統出錯的概率也就越來越大。
通過業務分析我們能夠得知,用戶的實際的核心流程其實只有一個,就是用戶注冊。而后續的準備支付寶,通知sns等操作雖然必須要完成,但卻是不需要讓用戶等待的。
這種模式有個專業的名詞,就叫最終一致。為了達到最終一致,我們引入了MQ系統。業務流程如下:
主流程如圖3-3所示:
圖3-3-用戶注冊流程-引入MQ系統-主流程
異步流程如圖3-4所示:
圖3-4-用戶注冊流程-引入MQ系統-異步流程
notify-消息中間件(2)
核心原理
Notify在設計思路上與傳統的MQ有一定的不同,他的核心設計理念是
為了消息堆積而設計系統
無單點,可自由擴展的設計
下面就請隨我一起,進入到我們的消息系統內部來看看他設計的核心原理
為了消息堆積而設計系統在市面上的大部分MQ產品,大部分的核心場景就是點對點的消息傳輸通道,然后非常激進的使用內存來提升整體的系統性能,這樣做雖然標稱的tps都能達到很高,但這種設計的思路是很難符合大規模分布式場景的實際需要的。
在實際的分布式場景中,這樣的系統會存在著較大的應用場景瓶頸,在后端有大量消費者的前提下,消費者出現問題是個非常常見的情況,而消息系統則必須能夠在后端消費不穩定的情況下,仍然能夠保證用戶寫入的正常并且TPS不降,是個非常考驗消息系統能力的實際場景。
也因為如此,在Notify的整體設計中,我們最優先考慮的就是消息堆積問題,在目前的設計中我們使用了持久化磁盤的方式,在每次用戶發消息到Notify的時候都將消息先落盤,然后再異步的進行消息投遞,而沒有采用激進的使用內存的方案來加快投遞速度。
這種方式,雖然系統性能在峰值時比目前市面的MQ效率要差一些,但是作為整個業務邏輯的核心單元,穩定,安全可靠是系統的核心訴求。
無單點,可自由擴展的設計
圖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億消息的時候,整個系統表現非常淡定可靠。在真正的大促到來時,我們的后端系統響應效率好于預期,所以我們很輕松的就滿足了用戶所有消息投遞請求,比較好的滿足了用戶的實際需要。