Friday, November 4, 2016

談五月天演唱會搶票 - 如何設計更好的系統

想要聽學長五月天的演唱會卻這麼難,開放的那一刻系統一打開就當掉,等到看到畫面的時候票也賣完了、拓元票務系統過不久便宣布他們系統掛了擇日再賣。想想發現這件事情其實跟我這學期在CMU修的每一堂課都有關連:

  • Information Security課講的Authentication, Fraud Prevention:抵制黃牛的記名機制
  • Packet Switch課講的Scheduling, Fair Queueing, Routing:公平性
  • Scalable System講的load balancing, database consistency, transaction, bandwidth, etc…:大流量系統設計

然後我發現這樣搶票有不少缺點:缺乏簡易有效的認證機制(用身分證不太有效率)、缺乏公開透明的購票狀態(大家只能看到圈圈在轉跟售完兩種狀態)等,於是我一直搶不到票。

拓元購票系統

搶票是統一時間大家一起連上線,所以拓元準備了很大的系統負載能力去等待這樣的流量,可以看到有不少機器在服務著所有的使用者:

> nslookup tixcraft.com
Server:     10.10.1.1
Address:    10.10.1.1#53

Non-authoritative answer:
Name:   tixcraft.com
Address: 52.36.104.197
Name:   tixcraft.com
Address: 52.37.22.23
Name:   tixcraft.com
Address: 52.33.63.158
Name:   tixcraft.com
Address: 52.88.158.112
Name:   tixcraft.com
Address: 52.37.88.199
Name:   tixcraft.com
Address: 52.35.97.122
Name:   tixcraft.com
Address: 52.34.117.237
Name:   tixcraft.com
Address: 52.26.7.103

同時為了防止黃牛買多過於正常消費者所需的票後轉售,也加上記名機制,透過身分證去驗證身份。然而網路上各種黃牛出現的新聞層出不窮,於是大家開始懷疑是否公平。
從我觀察的角度,每個人買到票的機率是差很多的,列舉幾個以下影響搶票成功率的變數:

  • 時間點:人的反應時間比電腦慢超級多,我們頂多可以控制在一秒內送出訂單,但是網路傳輸時間大約是10ms,系統反應時間更少。所以一個使用者要讓訂單在完全準確的時間出現在訂票系統面前是幾乎不可能用手動的。
wget tixcraft.com  0.01s user 0.01s system 16% cpu 0.112 total
  • 網路路徑:每個人連到票務系統的路徑是不同的,有的人剛好離系統主機近,所以比較有利,有人比較遠,所以反應速度慢等等,簡而言之,如果我們去看一個個的封包怎麼傳到對方系統的,會發現完全是不公平的,而且也是不應用程式能夠控制的(例如IP是怎麼route過去也是BGP互相同步後的結果)。可以用traceroute tixcraft.com看自己電腦怎麼連過去到對拓元系統的。

設計一個更好的系統

於是腦中就蹦出一個很粗略的系統設計想法,針對以上問題或許可以得到解決。先撇開商業層面,只討論技術的話,我覺得以下設計可以提供公開透明、公平、成本低的五月天演唱會訂票系統。

我把這個設計分成三部分解釋:

抽號碼牌後統一放榜

應該訂定一個時段(幾天的時間)讓大家有充裕的時間可以慢慢填寫資料、選時段與區域,並同時看已經有多少人登訂了哪些時段與區域。而這時候系統只會發出一個流水字號的號碼牌而非真正的門票。於是我們避免掉大家同一時間上線的高峰流量問題,同時大家也自動在看到數據之後自己分流到不同場次或區域。

使用手機號碼認證

登入系統開始選票之前,應該讓該帳號綁定一個手機號碼,並透過簡訊認證(成本約1元),唯有認證成功的帳號才可以開始訂票。由於手機號碼不容易被假造,所以可以有效控制黃牛問題。

放榜

放榜:就是領到的號碼牌有沒有真的抽到門票的意思。號碼牌可使用流水字號,所以是滿公開透明的,而系統只需要從這些號碼裡面亂數選出跟位置供給量一樣多的號碼給予門票即可。至於亂數公平與否可以使用公開的演算法如下:

In [1]: import random
In [2]: random.seed(555555) # can be picked by Mayday
In [3]: random.sample(set([1, 2, 3, 4, 5]), 3) # pick three from the set
Out[3]: [4, 5, 3]

由於演算法是公開的,有同樣seed值的人都可以算出同樣的數字,也可以算出自己有沒有中獎。至於怎麼選seed值就可以很有趣啦,像是讓五月天用抽樂透那樣的方法抽在宣傳上也滿好玩的。

其他細節

  • 信用卡可以於第一次登記領號碼牌時候就填上,而被抽到或有真正門票時候系統才刷卡
  • ATM轉帳實在是很古老的方式(雖然很多人在用),個人認為想規模化的系統不該用ATM轉帳
  • 這篇文章從想法出現到寫完只花了一個小時,若有不周之處請見諒

所以說?

讓大家同一時間搶票這件事情跟DDoS那個購票系統似乎沒什麼差別了,要在這麼高流量的情況下又保持好購票流程的完整性實在很困難。能夠從設計上分散流量是根本的解決方法,公開的選擇抽獎機制才會最接近100%的公平,且使用一般常見的認證機制如手機簡訊比較能實際的防止黃牛。

誒,我只是想看個五月天演唱會呀。

p.s.對於以上內容感興趣,或想實現的人歡迎跟我聯絡 http://www.heron.me