技術學習年貨之--交易核心鏈路的故事
第八年的雙11全球狂歡節已經落下帷幕,讓人印象深刻的1207億再次創造了曆史,雙11也從此進入了千億時代。今年雙11宗旨“全球化、娛樂互動化、無線化、全渠道”在活動中體現的淋漓盡致,從狂歡城、線下VR遊戲捉貓貓、到雙11萬星璀璨的晚會,讓無數人驚歎雙11成為全民娛樂盛宴。在娛樂狂歡的同時,雙11回報消費者最直接的就是買買買,“買出新生活、買出新高度”代表了無數剁手黨的聲音,為了讓消費者買的爽、買的值,天貓也是用盡了洪荒之力,從全球精品的低價預售,到狂歡城數十億的紅包、購物券,雙11當天更是火山紅包、密令紅包雨下個不停,再到品質商品半價、下午場滿n免一,讓消費者經曆一波又一波高潮,停都停不下來。
圖1 雙11多樣的玩法
每筆剁手之旅的背後都經過了哪些產品係統的處理,瞬間的剁手快感下麵又發生了什麼樣的信息速遞,我們通過一張圖來感受。
圖2 交易核心鏈路示意圖
令人眼花繚亂的活動,背後是怎樣的體係來支撐起這樣多元化的玩法,接下來我們一層層的來解構。在每秒17.5w筆的高峰下,每筆訂單所經的鏈路眾多,如何海量的訂單有序、準確的運行,如絲般潤滑,需要完整的業務、技術架構和對高峰時刻技術的攻堅。
2.1紅包發放
紅包發放需要保證精確的預算控製,即一個預算發出去的紅包的總金額不能超過其預算金額。一個預算維護在一條DB記錄中,對於紅包火山等大訪問量的活動,這將成為單點熱點瓶頸,同時還會導致單表記錄多過多,數據嚴重傾斜。
預算控製因與買家無關不需要實現單元化,而用戶的紅包信息需要實現單元化,發放不單需要考慮預算的扣減,還需要考慮預算扣減後用戶側需要盡快透出紅包。因非單元化與單元化數據分布在不同的數據庫以及機房中,這會導致跨機房調用,引入了更多不確定性因素。
1、挑戰
如何應對單預算超過幾十萬的發放QPS,以及在2秒內透出用戶獲得的紅包。為保證精確的預算控製,決定采用數據庫的方式來管理預算,而按照之前的常規優化方式,單記錄的發放QPS上限不超過4百。跨機房的網絡通信也不能保證100%暢通,萬一預算扣減成功後用戶紅包數據寫入失敗了如何感知並處理。
2、分桶方案
通過分析過往活動數據,我們將預算拆分為多個子預算,然後平均分布到多個數據庫中,並根據紅包發放請求中的用戶Id路由到不同的子預算中。在子預算餘額不足時,則路由請求至主預算中。多個子預算的扣減並不會完全相等,那麼必然有一部分先發生餘額不足,所以主預算需要比子預算多分配一些金額。當多個預算的餘額都非常少的時候,可以進行子預算的回收動作,避免預算劃分的碎片化。
圖3 分桶方案
3、SQL優化
為了提升單記錄的寫入性能,我們對寫入的SQL做了優化。紅包發放的場景主要有三條SQL,兩條插入語句和一條更新語句,更新語句是導致熱點問題的根源,為了減少更新導致的獨占鎖,我們使用將三條SQL語句放在一起,僅通過一次網絡傳輸就可以到達數據庫服務器中。同時為更新語句設置條件以保證更新後的餘額大於等於零,這樣的寫法可以做到扣減之前不用查詢預算的餘額,僅通過判斷SQL返回的錯誤碼就能識別是不是餘額不足,減少數據庫服務器的壓力。為更新SQL添加COMMIT_ON_SUCCESS標簽,保證事務成功後立即提交當前事務,不用等待客戶端獲得更新結果後再次發起COMMIT請求,減少了1次來回的網絡交互,同時記錄的獨占鎖可以立即得到釋放。為更新SQL添加TARGET_AFFECT_ROW 1 標簽保證如果滿足條件的記錄不存在,事務應該失敗因不是成功並且影響的行數為零。
通過和DBA的溝通,我們還采用了集團DBA團隊開發的數據庫熱點補丁,並且修改了數據庫的磁盤寫入參數,以10個事務為一個寫入單位。
4、效果
采用前述的SQL優化方案後,單記錄的發放可以穩定在8千左右的 QPS,摸高到大約1萬 QPS。在32個庫聯合壓測的過程中,我們發現了因sequence分配原因導致無法超過5萬QPS,對sequence的分配SQL采用前述的優化思想優化後,順利達到接近30萬的QPS的性能。此時數據庫與應用的性能都表現都比較平穩。
2.2紅包展現
當用戶獲得紅包後,我們需要在多個透出界麵中展現用戶的紅包。這些信息將包括用戶一共有多少個紅包可用、總計金額多少,以及詳細的紅包信息。統計這些信息是一件比較消耗數據庫性能的事情,而擁有紅包的用戶是很可能在短時間內多次查詢這些信息的。
為了減少數據庫的減力,很自然的方案是使用緩存,記住用戶前一次查詢的結果。而問題的焦點就轉變為了如果確定緩存應該失效,我們要在紅包的多個生命周期節點裏做關聯邏輯才能確認緩存的失效,而這樣的改動工作量會比較大,同時多次這樣的工作很可能是沒有意義的,因為用戶很可能一次也沒有看過他的紅包。因為我們每次在進行紅包狀態的更新時,都會更新gmt_modifed字段的值為當前時間,這是一個通用準則,於是我們有了如下的緩存方案:
構造緩存時,采用事務內的一致性讀取數據庫當前時間做到緩存生成時間,如果該用戶沒有紅包數據,那麼緩存生成時間取2000年1月1日。當用戶查詢紅包數據時,我們先執行一次SQL查詢返回用戶對應紅包數據的最後更新時間,“然後比較這裏返回的時間與緩存生成時間的關係,當用戶紅包數據的最後更新時間大於或等於緩存生成時間時,判定緩存失效。這樣的判斷方式非常準確,同時因為可以利用數據庫索引且僅返回很少的信息,數據庫性能消耗的並不多。
圖4 紅包查詢方案
2.3 紅包使用
紅包使用的場景需要支撐超過8萬QPS的峰值。業務上的規則是一次下單最多可以10個紅包,那麼對於我們來說,將需要更新10個紅包的狀態,產生10條紅包的使用流水記錄,並且還需要產生至多10條紅包相關的業務單據。而通常的情況是用戶的一次下單行為所涉及的紅包會被全額使用。
1、SQL優化
通過SQL分析我們發現在紅包使用場景中數據庫花費了大量的CPU資源進行SQL解析,同時一次下單涉及的SQL語句也很多,有非常多的網絡消耗。而mysql並不像sqlserver等數據庫那樣支持預編譯,但好消息是mysql支持batch insert語法。於是我們可以使用batch insert的語法來優化插入性能,使用一條UPDATE SQL更新多條紅包的方式來優化更新性能,然後再將些SQL使用前麵提到過的合並優化方案合並為一條大的SQL語句發送給數據庫服務器,減少網絡交互。假定本次用戶下單時全額使用了3個紅包,那麼可以通過一個SQL將三個紅包的餘額更新為零,同時還使用了金額鎖保證紅包並沒有其它的事務並發更新。同時為更新語句添加TARGET_AFFECT_ROW 3的標簽,如果紅包已經被其它訂單在並發場景下使用,那麼它會使當前事務失敗,並且我們可以通過數據庫返回的錯誤碼識別這一情況。
2、效果
通過前述的優化措施,在典型的場景下,數據庫服務器的負載下降了至少50%,而且下單的整體響應時間也減少了至少50%。
2.4紅包係統可靠性保障--一致性消息通知
前麵有提到紅包的發放隻是扣減了非單元化場景的預算,然而我們還需要在預算扣減完成後寫入單元化場景的用戶紅包數據。它們處於不同的數據庫,我們需要有機製來保證它們的一致性。除了一致性,還有時效性的需求,因為我們需要在發放成功後2秒內就能展現用戶的紅包數據。普遍的方案使用跨庫事務框架來解決問題,但是輕量的跨庫事務方案不能做到嚴格的事務一致性,而嚴格的跨庫事務一致性方案顯然是相當重的,它會極大的降低性能。加上我們還有內部業務流程串連的需求,所以便產生了一致性消息通知-hjbus。
hjbus的思想在是業務的事務中插入一條消息記錄,建立一套消息的訂閱與分發係統來支撐消息的處理。因消息記錄與業務記錄存在於同一個數據庫中,可以做到事務一致性。消息記錄並不大,並且多個訂閱者共享同一條消息記錄,因此並不會增加過多的數據庫性能消耗。目前我們已經可以做到生成的消息在1秒內就可以消耗,因此可以保證用戶的紅包數據透出時效。
圖5 一致性消息通知-hjbus原理示意
同時通過消息積壓的監控,我們可以及時的發現哪些消息的消費出現了問題,出現了什麼問題,保障業務各流程的完整性。在一係列的優化工作完成後,我們的紅包係統在雙11前後都表現的相當穩定。
雙11當天交易下單峰值達到了創紀錄的17.5萬筆每秒,而每次下單都需要完成優惠的計算、紅包的使用等一係列的操作,對整個係統的調用量實際遠遠高於17.5萬每秒。如此高的並發,加上交易係統在數據上不能出任何差錯的特點,對係統的性能和穩定性方麵的要求都非常之高。
3.1前置處理,提升性能和穩定性
我們的下單係統需要訪問物流係統獲取運費模板,並計算運費的價格,在以前的架構中,這需要調用遠程的一個係統,由那個係統準備好相應的數據,計算結果後返回。這種方式會把下單的峰值帶到下遊所有的依賴係統中,也就會要求下遊依賴係統具備峰值同等級的能力,這不僅使得整體成本很高,而且下遊係統的穩定性也會影響整體下單的穩定性,在依賴關係非常複雜的交易係統中對整體穩定性帶來了很大的挑戰。
把功能前置後,需要計算運費時,下單係統無需請求一個下遊係統,而是直接訪問存儲著運費模板數據的緩存服務器,並通過前置在下單係統中的運費計算模塊,直接在本地計算出運費。這種方式不僅減少了遠程服務調用的網絡開銷,帶來了性能的提升,同時也減少了下單係統依賴的下遊係統個數,增強了係統的穩定性。
我們對很多下遊調用采用了功能前置的架構優化,通過雙11當天的驗證,這種方式在高峰情況下表現突出。
3.2 架構升級,提升開發效率和可靠性
雙11的挑戰不僅僅是性能和穩定性,由於參與雙11的業務團隊數量越來越多,業務玩法也越來越豐富,所以直接參與到雙11業務開發的團隊個數和開發人數也越來越多。眾多的團隊和開發人員,同時在一個平台上開發,怎麼提升開發效率也是很關鍵的一個點,這關係到是否能按時完成需求的開發。
針對多團隊協同開發的場景,交易平台去年完成了架構的升級,在新TMF2框架(見圖 6)下,業務級的代碼和平台級的代碼進行分離,平台級代碼對於交易的能力進行分類、抽象並對外透出,業務方的開發團隊能力自助地利用平台提供的能力完成各自業務的定製邏輯的開發,無須依賴平台團隊介入,從而大幅度提升整體業務開發效率。
圖6 TMF2整體架構
TMF2 作為業務與平台分離的業務框架,主要通過兩大類模型(能力模型、配置模型),並基於這兩大類模型生成的配置數據來貫穿兩個業務活動主線(業務配置主線、業務運行主線),詳見圖7。
圖7 TMF2框架模型圖
通過對交易建模、抽象和收斂,形成了交易域基礎能力層,提供了各交易需要使用的核心能力,采用功能域-》能力-》擴展點方式進行表達。
例如,在合同訂立(下單)環節歸納有十幾個功能域,比如優惠、支付、交付、價格、訂單、結算、稅費等。這些域裏的能力又通過擴展點的形式開放給業務方開發做定製,以適應其不同業務場景的需求。
在此基礎上還引入了產品的概念,它是包裝了多個域的能力,對業務方提供了能滿足某種業務功能的能力包,從而使得業務能直接使用,加快業務開發效率。比如預售產品。業務能力和產品,通過業務場景串聯,從而形成一個完成的業務解決方案。
在這個架構中,業務能力、產品和場景屬於平台能力,業務方的定製功能都存放於業務包中,這樣的架構可以做到業務於平台分離、業務之間隔離的效果。從而使得平台的開發人員和業務的開發人員之間互相不幹擾,而不同業務的開發人員之間也互不影響,這極大的提升了多團隊同時協作的效率,從而提升了整體的效率。
2016年雙11,營銷平台是天貓與淘係優惠係統合並後的第一個雙11,在係統性能、穩定性、數據一致性上遇到了諸多挑戰。下文主要是闡述營銷平台係統在高性能、數據一致性上遇到的挑戰與解決方案的實踐,最後再介紹主要的玩法“雙11購物券”從招商到交易過程中,我們的解決方案。
4.1營銷平台雙11整體架構
營銷平台包括2個交易核心係統,分別是UMP(圖中紅色部分)與PromotionCenter(圖中黃色部分)。
UMP負責所有優惠計算、優惠在導購與交易鏈路中的透出,包含三部分:
1、UMP的核心是優惠計算。例如,折扣價是多少,這筆訂單能用多少的雙11購物券,抵扣多少金額;
2、優惠規則引擎負責處理優惠與優惠之間的關係。例如,店鋪優惠券能和店鋪滿減活動疊加使用;
3、狼煙多級緩存框架負責將優惠數據根據功能、熱度等因素分配到多級的緩存中,同時屏蔽了不同緩存的實現。
在2016年,UMP整合了天貓優惠係統,將原天貓優惠的所有功能與數據都完整的遷移到了UMP中,今年雙11和去年相比,調用鏈路、數據流都發生了巨大的變化。PromotionCenter是權益平台,負責權益的傳播、權益的管理。目前主要的權益包括:卡券(店鋪優惠券、店鋪紅包、商品優惠券、天貓購物券、雙11購物券等)、優酷會員等。
4.2數據一致性實踐--通用數據對賬平台
雙11對於營銷平台的挑戰,先從數據說起。由於營銷都是在和錢打交道,錢算的不對,帶來的就是資損,所以數據的一致性對於業務正確性來說,尤其重要。
4.2.1 數據一致性的挑戰和目標
1、優惠數據產生與使用過程會經曆多種數據源(DB、TAIR、Vsearch等)
2、單元化部署結構導致數據會在多個機房中存儲
3、優惠與外部如資金,搜索等都有關聯,數據鏈路異常複雜
4、缺少主動發現和補償機製來保障數據的最終正確,可能引發投訴與資損
4.2.2我們建立的通用數據對賬平台的目標
1、抽取底層模型,形成統一的結構
2、支持多種數據源,如db與tair等,自定義對比方式
3、支持增量與全量對賬
4、業務可配置化,能快速上線,發現線上不一致問題,以及相應處理與報警
通用數據對賬平台(DataCheck,簡稱DC)整體架構
底層基於JStorm 實時流式計算框架作為運行的基礎,上層增加了任務調度管理,數據源、對賬腳本管理、監控報警管理等模塊。用戶可以通過實現簡單的對賬腳本,就可以完成數據的對賬工作。
離線對賬,通過chronus定時調度程序,掃描DB或者定時拉取雲梯表的數據,將需要對賬的內容組裝成metaq消息,DataCheck根據消息內容執行對應的數據對賬腳本(數據對賬需要預先在百寶箱中配置好),最終的執行結果。
實時對賬,與離線對賬的差異在於觸發的機製不同,實時對賬通過DB的DRC消息觸發,精衛通過消息觸發DataCheck進行對賬。
4.3多級緩存框架實踐 —— 狼煙多級緩存框架
在UMP整合了天貓優惠係統後,由於天貓賣家中,會有大賣家,如:貓超、當當網、優衣庫。每到大促,熱點數據成為了我們關注的問題。UMP由於實時性的要求,是一個重度依賴緩存的係統。如何防止熱點數據擊穿,提升熱點數據的訪問效率,我們建立了一個多級緩存框架來解決這個問題 —— 狼煙。
4.3.1 狼煙三級緩存結構
1、預熱緩存,在雙11大促裏我們是可以預測出一些熱點數據和必定極熱的賣家維度數據。這種促銷級的活動在一定的周期內是禁止編輯的,在開始的周期內將預測的熱點數據提前寫到本地緩存。在16年雙11,狼煙做到了在3分鍾內完成7千多台機器、幾個G數據的預熱。具體實現有堆內、local tair(堆外)
2、熱點緩存,存儲在應用中的活躍數據,一些無法預測買家購買行為的數據可以按照周期內QPS排序,保證Top熱點常駐在零點裏。我們和sentinel團隊的子矜合作,提供了初步想法,最後由子矜完成hotsensor,采用hotsensor來防止黑馬熱點的問題。
3、全量數據緩存,一般采用tair實現,支持ldb與mdb
4.3.2 狼煙特性
1、統一接口
由於不同緩存有不同的實現,接口差異性較大,在狼煙裏封裝了統一的API,業務代碼在應用時,無須關注底層實現
2、流程控製
狼煙支持在多級緩存獲取的流程上,做到細致的控製,如各級緩存的寫操作、tair&db一體化、db限流等等
3、緩存控製
在狼煙裏可以做到任意一級緩存的可拆分,可以細粒度到隻訪問某一級緩存(包括db,在狼煙裏db也是統一的一套接口,由應用提供回調)
4、預熱緩存
狼煙采用蜻蜓進行分發需要預熱的數據,采用統一的數據結構包裝預熱的數據,在單機生成數據(文件)後,提供數據獲取接口給到蜻蜓進行分發,分發的流程如下圖
圖8 狼煙分發原理
5、熱點緩存
高峰期驅逐策略:兩小時內數據有效,在周期內針對數據訪問的qps和最近訪問一次時間點進行排序,排在最後麵的驅逐。熱點緩存依賴了hotsensor進行熱點的計算,hotsensor針對周期內的單位時間做了一個滑動窗口。采樣窗口長度設為1.5s或2h,這個采樣窗口又被分割為20個格子。通過用一定的算法來統計這20個格子的平均滑動窗口累積平均值來進行統計
計算公式:
6、數據處理
在涉及到多級緩存時,未命中的key到下一級進行查詢,多key的情況(譬如常見的:mget、mprefixGet、mprefixGets)需要組裝每次的查詢結果,去識別到每一個key。代碼量比較多且重複,在ump裏麵充斥著大量的組裝返回結果的代碼,在應用狼煙後,清理了一大批這樣的代碼,用兩三行去替換之前幾十上百行代碼,大大增加了代碼可讀性。
4.3.4 狼煙在2016雙11表現
1、預熱緩存:優惠活動數據,命中率為百分之十幾,減少到Tair百分之十幾的調用量。;卡券規則數據,命中率近乎100%,應用基本不需要訪問Tair獲取這部分數據。
2、熱點緩存,0點峰值整體命中率為20%左右,支持單key最高40多萬的 QPS訪問,沒有出現擊穿緩存到DB的情況。
業務中台,電商鏈路的基石
交易,營銷,資金隻是業務平台事業部的一部分功能,除此之外部門還有商品,會員,店鋪,商戶,電子憑證,LBS,數據,評價,規則和內容功能單元。單元之間無縫的銜接構建了阿裏集團電商板塊業務的全鏈路業務支撐技術體係,除了耳熟能詳的三淘之外,還有很多新興的業務。利用了平台提供的模塊化、可視化配置的技術組件,開放服務和元數據來快速定製獨特的商業形態,多個渠道的商業數據又通過Imap技術動態歸一沉澱,為平台治理和商家多渠道鋪貨提供便利。
業務平台事業部承接集團“大中台,小前台”戰略業務層部分,以支撐業務方快速,低成本創新的能力為目標。然而,業務中台並非部門一己之力來建設,集團的技術團隊都是業務中台能力的提供者,沒有團隊界限,隻有”高效實現業務”的共同目標。按照一致的標準和協議注冊到中台,確保模塊之間的連通性,避免重複低效建設。隨著業務的頻繁上線,不斷沉澱、打磨、升級能力,技術同學發現自己精心打造的能力被多個業務使用,真是莫大的鼓舞!步入良性循環的運營機製,業務實現的效率越來越高。
雙11是業務平台事業部難得一次的全員大練兵,我們用實力和勇氣證明了自己,然而我們卻願意退居幕後鍛鑄平台,支撐前端豐富多彩的繁榮生態。今天最好的成績是明天最低的要求,我們仍然保持追求極致用戶體驗,性能,穩定的目標,用技術拓展業務邊界,為業務方提供簡單,可信賴的電商技術基礎產品,高效高質量地支持前端業務快速發展和創新,這是我們的願望,也是我們的使命!
最後更新:2017-06-28 14:31:55