核心交易系統架構演進
前言
隨著雙11進入千億時代,電商平臺正在向“全球化,娛樂互動化,無線化,全渠道”發展。
為實現全民互動,電商平臺會進行低價預售,狂歡紅包,購物券,紅包雨,商品半價,滿n減1等多種促銷方式。
核心交易鏈路設計
每筆剁手操作都會經歷一系列核心系統處理,如圖:
如此眼花繚亂的玩法,底層是多個核心繫統的支撐,整個系統要保證在交易高峰下的海量訂單有序,準確,順滑。
預算扣減及紅包領取
紅包發放要保證精確預算控制,預算髮放的紅包總金額不能超過預算的金額。
每條預算在資料庫中是一條記錄,在高併發場景下,可能會成為單熱點瓶頸,維護過多的記錄表,可能造成資料傾斜。
預算控制和使用者無關,無需實現單元化。使用者的紅包資訊則需要實現單元化,發放流程涉及到預算扣減,扣減操作後,使用者需要儘快收到紅包。
因單元化和非單元化的資料處於不同資料中心,可能造成跨機房呼叫,也就引入了不確定性。
所以紅包系統和預算系統需要解決高併發場景下的預算扣減和使用者收取紅包的一致性。
分桶方案
通過分析歷史資料,我們將預算拆分為多個子預算,瓶頸分配到多個數據庫中,根據紅包發放請求的userId進行路由。在子預算餘額不足時,路由到主預算中。
每個子預算的扣減並不相等,肯定有一部分子預算會出現餘額不足的情況,所以主預算要比子預算多分配一些金額。當多個子預算餘額非常少時,可以對子預算進行回收,避免預算分片的碎片化。
資料庫優化
為提升記錄表效能,需要對資料庫操作進行梳理及優化。設想這個場景主要有3條sql:
- 兩條插入語句
- 一條更新語句
更新語句是造成熱點的瓶頸,為減少更新導致的獨佔鎖,可以將3條sql合在一起,通過一次網路傳輸到達資料庫伺服器,同時在更新語句中設定餘額大於等於0的條件,這樣可以避免在扣減之前再查詢一次餘額,而僅僅通過判斷sql錯誤碼就能識別餘額是否足,減少了對資料庫的壓力。
更新語句新增commit_on_success標籤,保證事務成功後立即提交事務,不用等到客戶端獲取更新結果再發起commit,減少了一次網路互動,同時記錄的獨佔鎖可以立即釋放。
更新語句新增target_affect_row 1 標籤,保證如果滿足條件的記錄不存在,事務應該失敗,而不是返回影響行數為0。
可以將多個事務封裝成一個數據庫的寫入單位。整體優化後系統qps可以摸高到30w。
紅包展示
使用者領取紅包後需要在多個系統終端中進行紅包展示,比如領了多少紅包,金額是多少等。
統計這些會比較消耗資料庫效能,同時展示紅包也是比較高頻的需求。採用快取可以解決這個問題,但是隨之而來的問題是快取的失效處理。紅包本身涉及多個生命週期,到底在哪個緩解設定快取失效是合理的呢?
在使用者的紅包每次進行狀態變更時都會更新modify_time,所以採用讀時更新快取:
- 採用事務內一致性讀取快取,將當前時間設定為快取生效時間,如果使用者沒有紅包,則生效時間為2000年1月1日。
- 當查詢到使用者用紅包時,會同時查詢出紅包的最後更新時間,然後和快取生成時間做比較,當用戶紅包資料更新時間大於快取生成時間,則判斷快取失效。
- 這樣可以利用資料庫索引,同時減少返回資訊,對資料庫的消耗比較少。
紅包使用
在業務規則角度進行了紅包使用控制,每次只能使用10個紅包,紅包使用場景qps也很高放大到紅包系統qps是10倍。每次紅包使用需要更新10個紅包狀態,產生10條紅包使用的流水,還需要產生至多10條紅包相關的業務單據。
一次紅包使用場景涉及到大量cpu資源進行sql解析,一次下單涉及到多個sql,對網路消耗較大。我們採用batch insert語法優化插入效能,更新語句採用多條方式提升更新效能。在業務系統中生成一個大sql傳送給資料庫伺服器,減少網路互動。
比如這次下單操作涉及到5個紅包,可以通過一個sql將5個紅包餘額更新為0,同時加入金額鎖保證紅包的併發更新。設定語句的target_affect_row 5標籤,如果某個紅包已經被其他訂單併發下單使用,事務會提交失敗,可以通過資料庫返回的錯誤碼識別出這一情況。
可靠性保障
上面的情況只是處理非單元化場景預算,系統需要在預算扣減之後寫入單元化的使用者資料中。兩種資料處於不同資料庫,需要保證操作的一致性。同時在紅包領取後,在1s內展示使用者紅包,這種情況一般採用跨庫事務框架來解決。
但跨庫事務不能做到嚴格的事務一致性,嚴格的事務一致會造成效能的極大下降,於是採用內部的一致性訊息jbus實現。
jbus
jbus思想是業務在事務中插入一條訊息記錄,建立一套訊息訂閱和分發系統對訊息進行處理。訊息的記錄和業務記錄在一個數據庫中,可以做到事務一致性。
多個訊息訂閱者可以共享一條訊息記錄,因此不會增加過多的資料庫效能損耗。做到1s內訊息消費,則可以保證使用者看到自己領取的紅包。
同時建立監控系統對訊息擠壓進行監控,可以及時發現訊息的積壓問題,同時在消費出現問題時進行流程完整性的保障。
流程前置處理
下單系統涉及到訪問物流系統獲取運費模版,計算運費價格,之前的架構會呼叫遠端服務,獲取計算結果,這種方式會將下單峰值帶到下游依賴的系統中,需要下游系統具備同樣的峰值承載能力,提高了整個核心鏈路的成本,同時穩定性也帶來了複雜和挑戰。
流程前置處理後,下單系統不再需要請求物流系統,而是直接訪問運費模板快取伺服器,通過前置下單運費計算模組在本地計算出運費,減少了對於遠端服務的呼叫和依賴,提升了系統性能,增強了系統穩定性。
提升開發效率(TMF2)
隨著業務玩法的越來越豐富,參與的團隊越來越多,多個團隊在一套平臺開發造成的效率浪費越來越多。
為提升開發效率架構進行了升級,業務級程式碼和平臺級程式碼分離,平臺級程式碼對交易相關能力進行分類抽取,抽象提取對外提供支撐服務,業務方根據團隊能力自助式定製邏輯開發,無需平臺團隊介入,大幅提高開發效率。
為達到業務和平臺分離的架構目的,主要通過能力模型,配置模型,所生成對配置資料貫穿業務配置主線和業務執行主線來實現。
通過對交易建模,抽象,收斂,形成了交易基礎能力層,採用功能域->能力->擴充套件點方式進行表達。
在下單環節中歸納十幾個功能域,優惠,支付,交付,價格,訂單,結算,稅費等,針對這些域進行能力擴充套件,同時開放給業務方進行定製,適應不同業務場景需求。
同時引入產品概念,將多個域能力進行整合,對業務方提供滿足業務功能的能力包,進一步提高業務研發效率。
整個架構中,業務能力,產品,場景屬於平臺能力,業務方定製功能都在業務包中,這樣可以做到業務和平臺分離,業務之間隔離,使得平臺開發人員和業務開發人員之間互不干擾,提升整體協作和交付效率。
業務技術挑戰
營銷平臺核心系統:
優惠計算系統能力:
- 優惠計算,折扣價多少,訂單可用多少購物券,抵扣多少金額
- 優惠規則引起處理優惠和優惠之間關係,商家多少優惠券可以滿減券可以疊加使用
- 多級快取框架負責將優惠資料按照功能,熱度等因素進行多級快取,及快取的不同實現
交易系統和金錢打交道,稍有不慎會帶來資損,所以資料一致性和業務正確性是平臺最大的挑戰。
挑戰:
- 優惠資料產生和使用經歷多個數據源,db,tair,vsearch等
- 單元化部署結構導致資料在多個機房儲存
- 優惠和外部資金,搜尋關聯,業務鏈路複雜
- 缺少主動發現和補償機制來保障最終正確,可能造成客訴和資損
目標:
- 底層抽取模型,形成統一結構
- 支援多種資料來源,db,tair,自定義對比方式
- 支援增量和全量對賬
- 業務可配置化,快速上線能力,線上不一致發現能力,及時處理及預警能力
實時對賬:
底層基於storm流式計算框架,上層增加排程任務管理,資料來源,對賬指令碼管理,監控報警管理等模組。使用者可以通過實現簡單對賬指令碼,完成資料對賬工作。實時對賬通過db的drc訊息觸發。
離線對賬:
通過定時任務,掃碼db或定時拉取表資料,將需要對賬內容組成元資料訊息,datacheck根據訊息內容執行對應資料指令碼對賬,得到最終結果。
多級快取框架
交易相關核心鏈路每到大促時節,資料熱點都會變成最需要解決的問題。同時對於資料一致性有一定的要求,於是好的快取系統,做好防止熱點資料擊穿,提升熱點資料訪問效率就顯得尤為重要。
三級快取結構
- 預熱快取,通過歷史資料可以預測出一些熱點資料,同時參與大促的活動在一定週期內是禁止編輯的,活動開始後將預熱資料提前寫到本地快取中,實現堆內,堆外資料預熱
- 熱點快取,儲存活動相關熱點資料,無法預測的購買行為資料可以按照週期內qps排序,保障top熱點資料常駐快取
- 全量資料快取,可採用tair
特點:
- 統一不同快取實現的介面,業務程式碼無需關注底層實現
- 多級快取精細控制,各級快取的寫操作,tair&db一體化,db限流等
- 做到任意一級快取可拆分,粒度精細到某一級快取(包括db)
- 資料預熱,採用統一資料結構包裝預熱資料,單機生成資料(檔案)後,提供資料介面進行分發
如圖:
熱點資料快取與驅除
兩個小時內資料有效,在週期內針對資料訪問qps和最近一次時間點進行排序,最後的驅除。
hotsensor針對週期內單位時間做滑動視窗,視窗長度取樣採用1.5s或2h,取樣視窗劃分為20個格子,通過一定演算法統計20個格子平均滑動視窗累計平均值。
hotsensor計算方式:
多級快取場景中,某個key到下一級快取查詢,多key時需要組裝每次查詢結果,可以進行封裝,統一程式碼風格。
總結
利用平臺提供模組化,視覺化配置的技術元件,開放服務和元資料來快速定製獨有商業形態,多個渠道資料進行沉澱,實現了“大中臺,小前臺”的業務劃分,支撐了業務的快速發展和低成本創新的目標。
關注公眾號,獲取更多內容:
