作者| 阿裡文娛技術專家 古行
一、背景
大麥網作為現場娛樂票務平台,其業務覆寫了各大頂級演唱會和大型賽事等高流量項目。 票務行業庫存系統不同于普通電商庫存系統,瞬壓過高的秒殺搶票,多場景、多階段的售賣, 對一緻性和穩定性提出更高要求。本文将為讀者介紹現場娛樂行業票務庫存高性能和一緻性難 點解決和沉澱下來的庫存穩定性建設經驗。
二、庫存場景分類
在售賣中支援多管道:主辦方售賣、大麥網售賣、其他分銷管道售賣等。來滿足不同場景 下的票源管理。大麥網庫存可以分為無座庫存、選座庫存、預售數字庫存和現票庫存。
1)無座庫存:比如音樂節、遊展類項目,觀衆持票入場,無需安排座位;
2)選座購買:使用者可以自己通過座位圖選擇座位,下單購買;

3)預售數字庫存:預售階段使用者先按照票檔價位購買,然後系統按購買順序進行自動配座;
4)現票庫存:如非大麥網票務系統生産的,由大麥網從主辦方提取現票在大麥網售賣。
1. 庫存核心技術點
目标:高性能、強一緻性 庫存的高性能和一緻性主要從以下幾個方面保障:
1)進行事務拆分,執行粒度最小化,優化提高性能;
2)基于正向流水防止重複扣減;
3)基于逆向流水防止重複復原。
2. 扣減預校驗:防擊穿緩存設計
如果所有的庫存扣減攔截都放到最後一步扣減庫存來做,無疑會對資料庫造成巨大的沖擊。 畢竟庫存有限,總有一部分請求是無法購買成功的,這一部分請求流量應該在庫存實際扣減之 前攔截下來。
預校驗階段即“高并發讀”鍊路時,進行一些不影響性能的檢查操作,比如請求的合法性 校驗、票品是否可售、可售數量是否足夠、管道是否授權等。在這個階段,系統采用分布式緩 存來抵抗高并發讀。
傳統意義的緩存比如 Memcached,一個比較頭疼的問題是緩存擊穿。為了保護 DB,我們 對傳統緩存做了一層封裝,即在傳統緩存寫入時增加目前毫秒級時間戳屬性,讀取緩存後與當 前時間戳比較其內插補點判定其是否邏輯過期,如果邏輯過期則在競争分布式鎖後讀取 DB 資料并反哺緩存。
3. 庫存扣減的一緻性保障
庫存扣減要同時扣減票品庫存和管道庫存,是以扣減階段勢必要進行拆解執行,拆解成最 小粒度執行是為了命中資料庫熱點更新檔,達到快速執行的目的。但拆解後面臨的問題是如果一 個扣減動作執行失敗,如何復原已經執行的動作。基于分庫分表的限制,以上兩個扣減動作顯 然無法使用資料層的事務做保證。本庫存系統選用的是“職責鍊模式”進行庫存扣減步驟的定制化。
我們把“票品庫存扣減”、“管道庫存扣減”作為職責鍊中的兩個獨立 Action,任何一個 Action發生異常則向上抛出,在上層處理異常并復原已經執行過的 Action。確定“票品庫存”“管道庫存”的扣減共進退,理論上達到資料一緻性的事務保障。
在動态組合職責時,兩個 Action 的執行順序相當關鍵。在扣減順序上,首先扣減票品庫存, 因為票品庫存的共享性,在多管道同時扣減的情況下,票品庫存一般先于管道庫存售罄。是以 首先扣減票品庫存相較于首先扣減管道庫存可以減少很多復原情況的發生。
4. 庫存復原的一緻性保障
在復原職責鍊中,動态組合職責時,同樣講究執行的先後順序,與正向扣減剛好相反,首 先復原管道庫存,然後復原票品庫存。這樣在管道庫存已經復原的情況下如果復原票品庫存發 生異常,結合上述的扣減順序,票品庫存的超賣扣減幾率将大大降低。
5. 異常場景的實時對賬
交易系統與庫存系統之間的對賬可以讓雙方系統互通有無。如果交易系統在扣減庫存時發 生讀取逾時,庫存系統實際已經完成庫存扣減,但交易系統并未成功落單。則庫存系統在實際 扣減成功後會發起對賬消息,此時交易系統對賬結果顯示交易系統并未落單,立即主動發起庫 存復原請求,撤銷剛才的事實扣減。
6. 資料庫層面的極限優化
庫存扣減會在同一條票品庫存或者管道庫存記錄上“高并發寫”。此階段會直接面對資料庫 的一條記錄進行高頻次的寫操作,業界普遍采用的方案是應用層排隊或者行級樂觀鎖保障對同 一條記錄進行操作的并發。考慮到應用層排隊有損性能,庫存系統采用了較為理想的資料層排 隊,主要基于阿裡的資料庫團隊開發的針對 InnoDB 層上的更新檔程式(patch),可以基于 DB 層 對單行記錄做并發排隊,進而實作秒殺場景下的定制優化。
7. 高并發場景下日志優化
業務日志對于發現業務問題極為有效,也有助于測試階段的問題定位。上線後有詳細的全 鍊路日志協助問題排查。為了避免引入的外部 jar 輸出不必要的日志,是以上線後的系統業務日 志級别調整為 ERROR 級别。另外,為了防止大搶期間日志落地造成 IO 競争導緻性能下降,庫 存系統裁剪了大量的無效日志輸出,并且采用 Logback 的 LoggingEventAsyncDisruptorAppender 異步寫日志,防止寫日志阻塞(極端情況下有抛棄日志的可能)引起的系統性能下降。
三、庫存穩定性
穩定性目标:2 分鐘内發現(業務監控 100%覆寫),5 分鐘内定位,15 分鐘内止血。
1. 鍊路梳理及優化
庫存紅線:是庫存系統的生命線,其規則如下圖:
強弱依賴:對庫存的核心鍊路進行強弱依賴梳理,保證核心鍊路隻依賴 DB,其他依賴均可降級。
2. 全鍊路壓測
完備的常态化全鍊路壓測體系,保證庫存的一緻性和性能符合大搶預期。
3. 大搶預案自動化
預案自動化的核心在于兩點:哪些項目是熱門項目?哪些預案需要執行? 1)發現熱門項目,預案根據 PV 和參與人數,自動發現熱門項目,加入預案執行隊列。
2)自動執行預案項,根據預先編排好的執行時間自動對搶票場次執行緩存預熱、開關降級和接口限流等操作。
4. 庫存異常熔斷
在搶票場景下,庫存異常的診斷是非常困難的,基于庫存扣減流水可以準确計算出庫存在 某一時間段内變化的情況,和目前生成的票單對比後即可以判斷庫存是否不一緻,進而觸發渠 道熔斷,防止情況惡化。
5. 監控及報警
在監控方面主要有:核心名額及異常監控、業務實時審計和周期巡檢。
1)核心名額及異常監控
核心名額及異常監控可以有效監控下單成功率和 RT 抖動,如果有異常錯誤碼或者抖動可 以及時發現,快速介入;
2)業務實時審計 業務實時審計是資料一緻性檢測的重要手段,由于鍊路逾時或異常下狀态不一緻的時進行
報警;
3)周期巡檢 周期巡檢是對上述監控的重要補充,業務實時審計其實是資料狀态變化觸發的,當沒有觸發事件或者沒有覆寫到其他規則時,周期巡檢可以避免監控遺漏,雖然是非實時的,但是也在實踐中起到不錯的效果。
6. 排查工具建設:快速定位,快速止血恢複
四、總結
以上是票務行業庫存系統建設及項目中的一些探索經驗,基于正逆向流水的防重,預校驗 攔截,防緩存擊穿,職責鍊模式的步驟拆分,系統間對賬,資料庫熱點更新檔的使用,日志裁剪 優化等一些列技術手段,達成庫存高性能、強一緻性目标。
通過梳理庫存紅線,常态化全鍊路壓測,異常熔斷機制,監控報警以及排查工具,大搶預 案自動化建設,持續提高庫存系統穩定性。