Categories
程式開發

大麥庫存的高性能及一致性是如何設計的?


一、背景

大麥網作為現場娛樂票務平台,其業務覆蓋了各大頂級演唱會和大型賽事等高流量項目。票務行業庫存系統不同於普通電商庫存系統,瞬壓過高的秒殺搶票,多場景、多階段的售賣,對一致性和穩定性提出更高要求。本文將為讀者介紹現場娛樂行業票務庫存高性能和一致性難點解決和沈淀下來的庫存穩定性建設經驗。

二、庫存場景分類

在售賣中支持多渠道:主辦方售賣、大麥網售賣、其他分銷渠道售賣等。來滿足不同場景下的票源管理。大麥網庫存可以分為無座庫存、選座庫存、預售數字庫存和現票庫存。

1)無座庫存:比如音樂節、遊展類項目,觀眾持票入場,無需安排座位;

2)選座購買:用戶可以自己通過座位圖選擇座位,下單購買;

大麥庫存的高性能及一致性是如何設計的? 1

(圖:大麥網選座購買)

3)預售數字庫存:預售階段用戶先按照票檔價位購買,然後系統按購買順序進行自動配座;

大麥庫存的高性能及一致性是如何設計的? 2

(圖:大麥網預售數字庫存購買)

4)現票庫存:如非大麥網票務系統生產的,由大麥網從主辦方提取現票在大麥網售賣。

  1. 庫存核心技術點

目標:高性能、強一致性

庫存的高性能和一致性主要從以下幾個方面保障:

1)進行事務拆分,執行粒度最小化,優化提高性能;

2)基於正向流水防止重複扣減;

3)基於逆向流水防止重複回滾。

  1. 扣減預校驗:防擊穿緩存設計

如果所有的庫存扣減攔截都放到最後一步扣減庫存來做,無疑會對數據庫造成巨大的衝擊。畢竟庫存有限,總有一部分請求是無法購買成功的,這一部分請求流量應該在庫存實際扣減之前攔截下來。

預校驗階段即“高並發讀”鏈路時,進行一些不影響性能的檢查操作,比如請求的合法性校驗、票品是否可售、可售數量是否足夠、渠道是否授權等。在這個階段,系統採用分佈式緩存來抵抗高並發讀。

傳統意義的緩存比如 Memcached,一個比較頭疼的問題是緩存擊穿。為了保護DB,我們對傳統緩存做了一層封裝,即在傳統緩存寫入時增加當前毫秒級時間戳屬性,讀取緩存後與當前時間戳比較其差值判定其是否邏輯過期,如果邏輯過期則在競爭分佈式鎖後讀取DB 數據並反哺緩存。

大麥庫存的高性能及一致性是如何設計的? 3

(圖:防擊穿緩存流程圖)

  1. 庫存扣減的一致性保障

庫存扣減要同時扣減票品庫存和渠道庫存,所以扣減階段勢必要進行拆解執行,拆解成最小粒度執行是為了命中數據庫熱點補丁,達到快速執行的目的。但拆解後面臨的問題是如果一個扣減動作執行失敗,如何回滾已經執行的動作。基於分庫分錶的限制,以上兩個扣減動作顯然無法使用數據層的事務做保證。本庫存系統選用的是“職責鏈模式”進行庫存扣減步驟的定制化。

我們把“票品庫存扣減”、“渠道庫存扣減”作為職責鏈中的兩個獨立 Action,任何一個 Action 發生異常則向上拋出,在上層處理異常並回滾已經執行過的 Action。確保“票品庫存”“渠道庫存”的扣減共進退,理論上達到數據一致性的事務保障。

在動態組合職責時,兩個 Action 的執行順序相當關鍵。在扣減順序上,首先扣減票品庫存,因為票品庫存的共享性,在多渠道同時扣減的情況下,票品庫存一般先於渠道庫存售罄。所以首先扣減票品庫存相較於首先扣減渠道庫存可以減少很多回滾情況的發生。

大麥庫存的高性能及一致性是如何設計的? 4

(圖:庫存扣減順序)

  1. 庫存回滾的一致性保障

在回滾職責鏈中,動態組合職責時,同樣講究執行的先後順序,與正向扣減剛好相反,首先回滾渠道庫存,然後回滾票品庫存。這樣在渠道庫存已經回滾的情況下如果回滾票品庫存發生異常,結合上述的扣減順序,票品庫存的超賣扣減機率將大大降低。

大麥庫存的高性能及一致性是如何設計的? 5

(圖:庫存回滾順序)

  1. 異常場景的實時對賬

交易系統與庫存系統之間的對賬可以讓雙方系統互通有無。如果交易系統在扣減庫存時發生讀取超時,庫存系統實際已經完成庫存扣減,但交易系統並未成功落單。則庫存系統在實際扣減成功後會發起對賬消息,此時交易系統對賬結果顯示交易系統並未落單,立即主動發起庫存回滾請求,撤銷剛才的事實扣減。

大麥庫存的高性能及一致性是如何設計的? 6

(圖:系統對賬交互圖)

  1. 數據庫層面的極限優化

庫存扣減會在同一條票品庫存或者渠道庫存記錄上“高並發寫”。此階段會直接面對數據庫的一條記錄進行高頻次的寫操作,業界普遍採用的方案是應用層排隊或者行級樂觀鎖保障對同一條記錄進行操作的並發。考慮到應用層排隊有損性能,庫存系統採用了較為理想的數據層排隊,主要基於阿里的數據庫團隊開發的針對InnoDB 層上的補丁程序(patch),可以基於DB 層對單行記錄做並發排隊,從而實現秒殺場景下的定制優化。

  1. 高並發場景下日誌優化

業務日誌對於發現業務問題極為有效,也有助於測試階段的問題定位。上線後有詳細的全鏈路日誌協助問題排查。為了避免引入的外部 jar 輸出不必要的日誌,所以上線後的系統業務日誌級別調整為 ERROR 級別。另外,為了防止大搶期間日誌落地造成IO 競爭導致性能下降,庫存系統裁剪了大量的無效日誌輸出,並且採用Logback 的LoggingEventAsyncDisruptorAppender 異步寫日誌,防止寫日誌阻塞(極端情況下有拋棄日誌的可能)引起的系統性能下降。

三、庫存穩定性

穩定性目標:2 分鐘內發現(業務監控 100%覆蓋),5 分鐘內定位,15 分鐘內止血。

大麥庫存的高性能及一致性是如何設計的? 7

(圖:庫存穩定性建設包含內容)

  1. 鏈路梳理及優化

庫存紅線:是庫存系統的生命線,其規則如下圖:

大麥庫存的高性能及一致性是如何設計的? 8

(圖:庫存核心紅線規則)

強弱依賴:對庫存的核心鏈路進行強弱依賴梳理,保證核心鏈路只依賴 DB,其他依賴均可降級。

  1. 全鏈路壓測

完備的常態化全鏈路壓測體系,保證庫存的一致性和性能符合大搶預期。

大麥庫存的高性能及一致性是如何設計的? 9

(圖:全鏈路壓測流程)

  1. 大搶預案自動化

預案自動化的核心在於兩點:哪些項目是熱門項目?哪些預案需要執行?

1)發現熱門項目,預案根據 PV 和參與人數,自動發現熱門項目,加入預案執行隊列。

2)自動執行預案項,根據預先編排好的執行時間自動對搶票場次執行緩存預熱、開關降級和接口限流等操作。

大麥庫存的高性能及一致性是如何設計的? 10

(圖:大搶預案自動化配置示例圖)

  1. 庫存異常熔斷

在搶票場景下,庫存異常的診斷是非常困難的,基於庫存扣減流水可以準確計算出庫存在某一時間段內變化的情況,和當前生成的票單對比後即可以判斷庫存是否不一致,進而觸發渠道熔斷,防止情況惡化。

大麥庫存的高性能及一致性是如何設計的? 11

(圖:基於時間軸的異常熔斷檢測)

  1. 監控及報警

在監控方面主要有:核心指標及異常監控、業務實時審計和周期巡檢。

1)核心指標及異常監控

核心指標及異常監控可以有效監控下單成功率和 RT 抖動,如果有異常錯誤碼或者抖動可以及時發現,快速介入;

2)業務實時審計

業務實時審計是數據一致性檢測的重要手段,由於鏈路超時或異常下狀態不一致的時進行報警;

3)週期巡檢

週期巡檢是對上述監控的重要補充,業務實時審計其實是數據狀態變化觸發的,當沒有觸發事件或者沒有覆蓋到其他規則時,週期巡檢可以避免監控遺漏,雖然是非實時的,但是也在實踐中起到不錯的效果。

大麥庫存的高性能及一致性是如何設計的? 12

(圖:票品健康監測示例圖)

  1. 排查工具建設:快速定位,快速止血恢復

大麥庫存的高性能及一致性是如何設計的? 13

(圖:排查工具包含內容)

大麥庫存的高性能及一致性是如何設計的? 14

(圖:庫存燃盡圖示例)

四、總結

以上是票務行業庫存系統建設及項目中的一些探索經驗,基於正逆向流水的防重,預校驗攔截,防緩存擊穿,職責鏈模式的步驟拆分,系統間對賬,數據庫熱點補丁的使用,日誌裁剪優化等一些列技術手段,達成庫存高性能、強一致性目標。

通過梳理庫存紅線,常態化全鏈路壓測,異常熔斷機制,監控報警以及排查工具,大搶預案自動化建設,持續提高庫存系統穩定性。

作者簡介

阿里文娛技術專家 古行

相關鏈接

10W 座位的大場館究竟是怎麼畫出來的?

10 倍高清不花!大麥端選座SVG 渲染

首次揭秘!看大麥如何掌控超大規模高性能選座搶票

3D/VR 選座技術探索