內容來源:2017 年 12 月 2 日,餓了麼研發總監石佳寧在“IAS2017網際網路架構峰會”進行《餓了麼交易系統應用架構演進》演講分享。IT 大咖說(微信id:itdakashuo)作為獨家視訊合作方,經主辦方和講者審閱授權釋出。
閱讀字數:3176 | 8分鐘閱讀
摘要
業務系統的演進主要取決於業務場景,業務場景的定義和認知是隨著公司發展而形成的,基本上有著一定體量的大公司技術架構都相對穩定,業務架構則主要是對業務發展產生影響,好的業務架構能夠保證業務更好的發展。本次嘉賓將會為大家分享餓了麼業務架構的演進之路。
當前形態
在講當前形態前首先要介紹下幾個基本概念。目前我們的所有業務系統都是嚴格按照領域做劃分和組成的,開發人員需要知道領域、鏈路和服務這幾個概念間的關係和定義,一旦能夠明確這些概念定義就能夠容易明白業務和系統之間的關係以及系統和系統之間在職責上聯絡。
交易領域
在餓了麼內部交易領域是相對大的範疇,是整個公司最重要的生命鏈路,所覆蓋的內容也並非是集中式的,而是分散在各個系統的職責上。比如客服系統看似和交易無關,但其實有交易職責的,因為它最終會影響到交易的結果。
因此我們定義從使用者下單開始一直到訂單完成為止,直接影響到最後訂單結果的內容都承載著交易的職責。
交易鏈路
交易鏈路是完成一筆交易所需要的最短路徑,這其中的任意節點都是不可缺失的,一旦缺少某一節點交易就無法達成。一個大的領域往往會有很多條業務鏈路,一般會有一條是最關鍵的,其餘幾條則是業務高點。
交易系統
交易系統相對就比較好理解了,所有的服務以一定的業務為邊界具體組成的明確部分就是交易系統。
上圖展示了參與交易的主要系統,可以看到除開訂單和支付系統之外,還有很多影響交易結果但不承載完整交易職責的系統也在其中,整個互動關係非常複雜。正因為一個交易領域作為交易系統的複雜要求,所以交易系統本身的職責是很容易混亂的。
業務特性和基本劃分
為了更清晰的確定交易職責,我們以交易訂單為基礎拆分出了正向鏈路和逆向鏈路兩個部分。
上圖是正向鏈路結構圖,可以清晰的看到從使用者下單、支付成功、系統確認到最後接單完成的整個過程其實是非常簡單的一個鏈路。
實際應用中也會將這個鏈路做的非常簡單,因為定義正向鏈路所承載的主要職責是讓一筆交易在技術和資料層面完好無損的走到最後。
這套服務的系統要求是在系統本身IO、資料的可靠以及穩定性上,一些複雜的業務邏輯不會放到正向鏈路中。正向鏈路要保證的是在大流量高併發情況下能夠處理的很好並完成每天千萬級別呼叫。
上圖所示的是逆向鏈路,它多出來了仲裁和交易取消申請等環節,逆向鏈路其實是以所有異常場景處理為核心職責的。它的定義與正向鏈路剛好相反,正向鏈路重的是系統本身的可靠和效能,逆向鏈路重的是所有複雜場景的處理。
我們在所有正常業務的處理過程中,尤其是新增的業務上一定會考慮逆向鏈路的支援。
服務架構
這套服務架構大概分為三層,最底層為通用服務,這一層在交易領域內的職能和服務能力是應該被大範圍複用的。
中間為核心服務層,是所有邏輯的承載,這一層分為交易支撐和交易保障兩部分,這樣的劃分和前面提到的鏈路其實是相似的,交易支撐承載的是流程職責,而一些業務場景會被單獨剝離出來放在交易保障中。
最上層是對接的業務系統,幾乎所以涉及到的交易系統都會對接底層的服務。
以這套架構為核心就會發現有大一部分是能夠存下來或者是可以複用的。
系統架構
我們的整個交易服務是比較垂直的,它的核心是流程,因為交易其實就是流程不停遞迴的過程。
整個系統架構的元件並不複雜,主要是Redis和MySQL。通過MySQL進行解耦,以防與其他系統有過多的互動。
當時的問題
在討論問題之前,首先分享給大家我們團隊內部一直在說的一句話。
▶架構層面的一切努力都是為了滿足業務的擴充套件性需要
做業務架構其實是比較務虛的一件事,不像做元件或者中介軟體的架構那樣有著明確的目標。業務需求的時刻改變使得業務架構的方案存在多種可能,結構人員需要在這些方案中選擇出對的那個,那麼怎麼才算是對的方案呢?
我們內部的評價標準是看這個架構能夠使用多久,未來的兩到三個月是否會消退掉。
遇到的難題
這裡將我們在整個架構演進過程中遇到的問題先列舉出來。
- 原系統職責龐大,維護和迭代成本很高,需要拆分。但是不知道怎麼拆,也很難對怎麼拆達成一致。
- 業務越來越複雜,介面和欄位越加越多
- 新業務對老業務會造成衝擊,相容永遠是考驗功力的
- 系統穩定性要求高,不管是新業務上線、老業務迭代、技術改造等,都不允許當機哪怕一秒。
案例-訂單與物流互動服務
訂單與物流的互動服務可以說是一個通用的案例,訂單服務承載外賣的交易,配送的運營由運單服務負責。
餓了麼的交易和物流是兩個大的系統,由兩個團隊分別負責。為了在這兩大體系間建立方便的對接,我們設想了一個訂單運單互動服務,讓訂單交易和物流之間的資料互動都通過它做中轉。最終我們實現了這樣的一個服務,並且把一定的職能從訂單服務和運單服務拆分出來。
在實現的過程中我們遇到了新的問題,首先這個互動服務出於效能和資料便攜的考慮快取了一部分的訂單或運單的資料直接從介面輸出。這樣的話交易鏈路上就多了一個掌握資料的節點,一旦整個鏈路出現資料不一致或者其他問題,排查起來會相當困難。同時其他各個服務的接入方無法判斷介面或邏輯的提供方,需要花費大量的時間溝通。
後來我們發現實現這套服務後整個開發效率反而更低了,最後我們還是將互動復的職責還回訂單服務和運單服務。
這讓我們意識到如果一個領域或系統的職責是清晰並獨立的,那麼就應該讓它直接被其他各個系統使用。另外對於系統的拆分和領域的識別要有共識,這個共識不僅僅是互動的雙方。
案例-新業務的形態支援
在購買餓了麼會員時生成的其實是一個虛擬訂單,當我們開始接收到類似這樣的業務需求的時候是有一點糾結的,因為原有的外賣訂單流程有部分是支援該業務的,只不過需要在此基礎上做一些相容,所以當時我們所面臨著在建立一套新的系統和在原有系統上做相容之間做出選擇。
最後我們選擇新增虛擬訂單服務,由業務形態以及當前邏輯的可複用程度決定,儘量服用,拆分(解耦)永遠比合並(內聚)容易
整體建議
基於以上所提到的案例,這裡做一個整體的建議。
- 一定要有一張完整全面的架構圖,以系統的維度標註出核心主鏈路,確保其始終清晰。
- 花時間去了解業務和它的發展,為未來做準備而不是直接做未來。
- 架構債務比程式碼債務更難還,評審checklist以及債務總結必不可少。
未來的發展
業務系統的發展往往緊隨業務複雜度,但是這裡有一個悖論,即如果業務都不知道如何發展,那麼業務系統就更別談發展了。
對此我們有一些思考和實踐,主要是在效率和效能方面。效率其實很好理解,就是如何改進架構使得更快的滿足業務前進。效能則是在原先系統業務的能力上進行擴充套件。這兩者並非互相違背而是統一協調的,一個好的設計效率提高的同時效能也會隨之提高。
基於這樣的思考,我們在內部做了一個嘗試,把我們對交易的理解付諸到一套系統上。交易無外乎幾個形態,物品的交換、資訊的交換和能力的交換,往往O2O或電商涉及到的都是類似能力的交換。
上圖就是這套系統的整個架構。最上層是導購前臺服務,負責與使用者的直接互動,是所有資料的入口。中間的交易中臺服務核心是合同的管理以及流程和能力的服務。最低層是所有的基礎支撐服務,店鋪、商品、賬戶這些資源都是基礎服務是交易資料的一部分,基於它們就會產生交易能力然後提供給前臺業務。