楠木軒

首次揭秘!大麥如何應對超大規模高效能選座搶票?

由 司馬盼香 釋出於 科技

背景介紹

隨著現場娛樂行業的不斷髮展,各類演出層出不窮,越來越多的演出開啟選座購票滿足用 戶的自主選座需求。大麥的選座不僅面向中小場館類的劇院演出,還面向大型體育賽事、大型 演唱會等超大型場館。

選座型別搶票的特點是“選”,由於“選”的視覺化以 及超大場館在資料量上對大麥是很大的挑戰。本文透過服務端和前端上的一些解決方案來探討 如何支撐超大規模場館的高效能選座,透過本文的一些技術方案希望可以對讀者在一些高併發 實踐中提供幫助。

核心問題

首先看一下普通商品的秒殺,拿某款手機秒殺來說,一般情況下,一場手機只有幾個型號, 比如中低檔、高效能檔、旗艦等,處理好這幾個商品的庫存即可。對於選座類搶票而言,每一 個場次的所有的每一個座位都可以認為是一個不同的商品,場館大小不一,大的鳥巢有 10w 座 位。也即是說一個選座類搶票就涉及 10 萬級別的商品,如果多個專案同時開搶,整體數量會很 龐大。目前大麥電商側的商品維度是票檔,座位並不是商品粒度,所以無法利用集團的秒殺能 力,選座類搶票涉及電商、選座、票務雲產銷,是對大麥整體能力的考驗。

先來看看整個選座購票的流程:以林俊杰長沙測試專案購票為例。

1、使用者開啟需要的場次專案詳情頁

2、點選選座購買,開啟選座頁面,檢視座點陣圖及票檔


3、選擇一個看臺區域,選擇喜歡的座位,點選確認選座


4、進入下單頁面,填寫手機號收貨地址,建立訂單


5、提交訂單完成付款、出票。其中,2、3、4 環節都與選座相關。從流程上看,選座的核心關鍵技術在於:

座點陣圖的快速載入。快速載入其實就是選座頁面的讀能力。選座頁面需要下載座位底圖、 座位基礎資訊來做渲染,同時需要票檔、該場次每個座位的狀態,來決定是可售還是鎖定還是已經售出。 對於大型場館座位 5 萬-10 萬,渲染一個選座頁面需要的資料量都很大;

高併發。由於熱門演出票的稀缺性,同時搶票的人數可能達到幾十萬。如何支撐如此高 的併發和吞吐是一大考驗;

座位狀態更新的及時性 當某個座位售出後,需要及時更新座位狀態;

搶票體驗:搶票時熱門的看臺某個座位可能幾十個人併發去搶,如何儘量提升使用者的體 驗,儘量讓更多使用者一次性購買成功,體驗更好。

高效能選座實踐

針對高效能選座的核心要求,我們從如下幾個維度去闡述我們在選座類搶票上的實踐。

1. 動靜結合

選座的瓶頸資料量“首當其衝”。從邏輯上講,一個座位完整的展現到使用者面前,需要包含 座位的看臺、排號、價格、售賣狀態等資訊,其中 看臺、排號等等是不變的,並可提前預知的;售賣狀態等時根據專案的進行會動態變化的。所以把選座的資料拆分為動態、靜態資料。對於 大型場館如 10 萬場館,使用者開啟一個選座頁,座位的靜態資料,這些資料大概 15M 左右。再加上動 態資料如票檔狀態、顏色、看臺狀態、座位狀態,10w 場館大概 2M 左右。

也就是說,如果不做處理使用者僅僅開啟選座頁就需要 17M 以上的資料量。如果選座資料儲存在 oss 上,如果每人下 載 15M,10w 人同時搶票則需要 1500G 頻寬,頻寬成本很高。為了解決靜態檔案訪問速度問題, 將靜態資料從 oss 直接接入到 cdn。同時為了保障資料最新,靜態資料採用版本控制。

2. 靜態資料的預載入

上面提到頻寬峰值很高,為了降低峰值且提升體驗,客戶端引入了靜態資料預載入。靜態 資訊結合預載入的處理,為處理大資料量的座位資訊提供了時間上的餘量,使用者在開啟選座頁 時優先顯示靜態資訊,可有效降低使用者等待時間,提升使用者的體驗。

透過大資料分析結合使用者的行為習慣,確定預載入的場次型別,提高預載入的命中率。


預載入 預解析,完成了繪製基本場館資訊的資料準備,再將資料提前與畫座 View 繫結, 預渲染 View 進而達到選座頁秒開效果。

3. 座位資料編碼

動態、靜態資料量大制約了我們實現高吞吐,同時也浪費了服務頻寬和使用者流量。所以需 要壓縮,壓縮到一定的可接受的範圍。只有資料量足夠小,才有辦法做到高吞吐。

1)靜態資料編碼

在處理大資料量的座位僅有靜態資料的預載入往往是不足的,預載入並沒有從根本上處理座位資料量大的問題,同時對於類似體育比賽這種多日期多場次的場景,由於預載入的使用存在快取量的控制,往往影響預載入的命中率。而資料重編碼和資料壓縮的使用,是從源頭解決問題的有效思路。

座位資料的重編,捨棄傳統的 xml 和 json 格式,不僅可以有效壓縮資料大小,還對資料安 全提供了保障,即使被拿到了介面資料,因為缺乏資料編碼的協議,也無法獲取有效的原始資訊。

2)座位靜態資料壓縮整體框架

目前大麥針對自己特有的座位資料特點,結合高效二進位制編碼方案進行座位資料的重新編碼,再使用通用的無失真壓縮進一步縮小資料體積,從而減少了座位資料的網路傳輸時間,從根本上解決大資料傳輸導致的時延問題:

基於二進位制的資料編碼,既保障了資料安全性,又保證了在資料解析中的高效性,即使數 據壓縮的使用也比 json、xml 的解析具有更少的時延。同時兼具工具化的批次生產方式,又進一步解決了資料構建問題。


透過端上和 server 端的握手協商過程,實現了資料編碼和通用壓縮方式靈活組合,sever 端 可以針對不同的端下發相應的壓縮格式檔案:


結合 CRC 的思想,制定了相容 IOS、Android 和 H5 三端的基於座位屬性的縱向 hash 校驗。相比 md5 等普通的雜湊計算方式,在處理 6 萬級座位多維度資訊時,在端上實現了十幾毫秒、 H5 側 50 毫秒左右的全量資料檢測,使得在不佔用多長時間的情況,可以驗證數萬級座位解析 的準確性。經過這編碼到檢測的完整鏈路,實現了減少資料的體積的同時,又能達到比傳統 xml 和 json資料的高效解析、高安全性。



其中 quantum 是大麥端上自研的基於動態位元和字典的壓縮演算法,結合大麥特有業務場景, 實現了高壓縮比和快速資料解析:


3)座位動態資料的編碼處理

a)動態資料的難點

選座動態介面主要涉及票檔情況、看臺情況、座位狀態。資料量最大的是座位狀態。以一 個 5 萬座位的場館為例,每個座位都要返回一個狀態供前端渲染。採用座位 id 和狀態鍵值對的 方式,由於座位較多使得整個返回結果過大,5 萬座位的場館返回 1M 以上的資料。

如果開啟 一個選座頁需要吞吐 1M 資料量的化,介面基本不可用了。之前的策略是按照分組策略,5 萬 大概會分 10 個組,這樣每個請求大概 100k 資料量,這樣才能達到介面基本可用,不過端上需 要請求 10 次才能拿到整個場次的狀態,可想而知效能會有多大影響。假如 5 萬座位的場館,10 萬峰值搶票,那麼僅僅這個介面就需要 100 萬的 qps,所以肯定會逢搶必掛。

b)方案

目前介面是透過 mtop 協議,我們思考的前提:目前 mtop 不支援 byte[]陣列流,只支援 json等格式的字串結構。如何把返回的資料減小,採用一個儘量簡潔的方案,同時呼叫一次返回 整個場館座位狀態,是我們努力的方向。

資料量大主要是因為有很多冗餘的座位 id。有沒有辦法不依賴這些座位 id?既然我們做的 動靜分離,靜態資料裡已經涵蓋了座位 id,我們動態接口裡只需要對應的返回狀態即可,即按 照靜態裡面的順序返回座位狀態。同時我們把返回結果進行簡單的相鄰狀態合併將進一步降低 返回結果大小。假設使用者選座座位符合正態分佈機率,平均長度 5w 座位平均返回不到 20k。

當然如果我們 mtop 協議支援二進位制流,那麼我們可以用 bit 位進行儲存,可以進一步降低 返回結果的大小。

4. 高效快取

1)快取

面向這麼高的 TPS,tair 是不二首選。採用 tair 本地快取,來支撐如此高的資料峰值。提到 tair,提一下我們這邊的一些策略。使用者進到選座頁是一個個的看臺,我們設計了一級 stand cache,即看臺級別的 cache;使用者會進行選座位,我們又加了一級 seat cache,即為座位粒度的 cache。兩級 cache 保障使用者查看臺和使用者下單選座都能命中快取。standcache 是熱點 key,從選座的場景是允許資料非準實時 的,所以引入了 tair localcache 和 guava localcache 來增加吞吐,以此降低對 tair 的讀壓力。

2)保護下游系統

目前採用的策略是 對下游的呼叫採用加鎖,tair 全域性鎖。拿到鎖的才去請求票務雲底層數 據。拿到鎖的程序去更新 tair 快取。其實從這裡看對 tair 的寫還是 qps 比較小的,但是每次爭搶 鎖對 tair 的讀還是不算太小。透過採用本地的鎖 隨機透傳來減少 tair 鎖耗費的讀 qps。為了 對下游依賴做降級,增加了資料快照,每次對下游的呼叫記錄資料快照。當某次呼叫失敗採用 之前的快照進行補償。

3)保障資料更新及時

由於我們採用了 tair 全域性鎖,可以按照秒級控制下游呼叫。呼叫採用非同步觸發。最短 1s 內 會觸發我們發起對下游的呼叫。如果我們想最大化利用票務雲庫存能力,給使用者的延遲在 1s 以 內,我們有一些策略。拿到鎖的執行緒 1s 內呼叫資料更新任務,在資料更新任務裡做一些策略, 1s 內是發起 1 次還是多次對票務雲的呼叫,呼叫越多 tair 更新越及時。由於使用者有一定的選座動作,一般情況下 500ms 的延遲使用者基本無任何感知的。

4)快取預熱 預熱一下快取,對使用者體驗和系統性能很有幫助。搶票類專案採用一定的策略做自動化預熱。

5. 安全及容災

1)安全

從上文看大麥座位資料做了編碼和加密,同時儲存路徑做了混淆,保障不到開搶時間座位資料無法被破解,保障了選座資料的安全性。此外選座頁佈局防控策略,保障是真正需要點選座位才能完成下單,防止機刷、防止繞過選座直接下單。透過類似策略降低了選座的無效流量, 提高了穩定性。

2)容災

選座主要在以下幾個方面做了容災。靜態資料儲存在 oss 上,目前採用跨地區儲存容災;tair 快取採用主備快取,出故障時可以做切換;服務端在 pc 和無線做了叢集隔離。

總結

本文透過在資料處理、選座效能、快取等等策略上來闡述了大麥高效能選座上的一些實踐。透過這些實踐目前大麥可以輕鬆的承載數十萬人的頂級流量的搶票專案。