車票售賣特點,有一張車票賣出去就會影響到整個列車線的票數:北京開往廣州的一趟列車有人買了石家莊到鄭州的票,同時意味著出發點在北京-石家莊,目的地是鄭州-廣州的所有情況都會少一張票。
1.最low的方法。每次查詢車票時候都算一遍各個站點的票數,取最小值。假設一共3站,北京,石家莊,廣州,共10個座位。有人要查詢北京-廣州的票:已經賣出了北京-石家莊9張票,石家莊-廣州1張票,取中間車站的最小值10-9=1,剩一張。這樣如果是20站查看兩頭車站的余票就要計算19次再找最小值。
為什么說它low呢?因為票數不多但是查看余票的人太多!而且人都不傻,在沒票時候還會刷新!所以來一次訪問計算20次,10萬人加上每個黃牛開10臺電腦用來刷票,瞬間訪問數達到100W,想要1秒內都得到響應需要1秒計算2000W次。
2.稍微好一點的方法。票被買走時候把每個車站余票計算一下,查看余票時候直接返回這個結果。同樣每秒100W訪問,但是只有1000人在這秒買到了票,計算余票時候只需要1000*20=20W次,省下了1800W次的運算。
3.更“實際”一點的方法。每隔1秒同步一次數據狀態。假設12306每次查余票需要更新1k數據,一般單個網卡1G帶寬,理論能同時支持12.8W的訪問量,100W人都要看就至少有8個服務器在工作,方法2中,余票需要存放8份的話就需要1000*8=8000次更新。還要考慮各個地區訪問的不均等性,電信,網通,鐵通等線路,整體列車余票情況數據量也有幾十K,所以1秒8000次更新也幾百兆的流量了。但是如果每隔1秒同步當前的數據狀態就好很多,這樣編程了1*8=8次,更新數據庫傳輸總量1M/s左右,差不多吧?
即便如此,還是扛不住訪問量。
因為電腦上12306是用的網頁模式,查詢車票那個頁面大小6K,即便是用了ajax,刷新一次北京-鄭州,這樣的大站需要傳輸7K的純json數據,個人感覺有很多字段都浪費了,沒什么用。
所以就我看來,12306可以做以下改進,不是一切問題都要用技術解決的。
1.已經做了,分段放票,減少扎堆
2.12306自制一款好的搶票軟件。既然搶票權在自己手里了,刷票軟件就少了,大量減少流量。
3.別搞現在的圖片驗證碼了,這些驗證碼刷不出來,辨識度低根本是暴力防刷,不但防機器人,真人都不行。
4.更改搶票規則,反正都是拼手速,拼網速,拼人品,何必這么費勁大家一頓刷刷刷呢?寫個算法分配下吧。
供需是主要矛盾,供大于求必定導致各種買不到票,沒辦法。
有些看官想學習高性能,高并發,分布式網站架構設計,我真心也不會......
建議看看看《大型網站技術架構_核心原理與案例分析_李智慧》,《大型網站系統與Java中間件實踐》這兩本書,《Hadoop實戰》這本也不錯。
由于12306這個開放性問題太大,我就只能說下為什么看到票卻買不到的最基本情況,權當拋磚引玉吧。
12306網站是全世界最繁忙的網絡之一,由于大量的人集中在某個時間點大量訪問該網站,導致網站的并發處理能力要求非常高。我是個it小菜鳥,就給沒有計算機基礎的各位看官講講皮毛知識,大牛莫笑。
網上有這么一個統計圖:
1.網站是怎么運作的。
一個用戶想知道現在有沒有票,于是打開網頁,網站的后臺就去查看自己的數據庫,檢索下有沒有用戶需要的數據,然后將結果展示到頁面上,就形成了頁面上的余票信息。
然后用戶看到:嘿~有票!買買買!點擊購買后,網站后臺將用戶訂票的信息在數據庫中更新一下:北京到巴黎的票100張變成了99張,然后購票成功。
我這里說的很簡單,沒有提到支付環節與退票,咱們先看這個簡單的例子,畫個圖大概是這個樣子的:
2.當有101個人都在搶票時候呢?
悲劇了,現在搶票更接近真實了,在早上8:00:00,有101個人同時要搶這100張票,會發生什么呢?對于一個人來說,網站實行“查看有多少票”(檢索數據庫),“買一張票”(修改數據庫)的時間非???,大約在50ms以內,所以很順利就執行了。但是101人同時點擊購買呢?全按照上圖的簡單流程,就多賣了1張票!所以需要再加一層檢查:
由于不止一個人同時買票,所以看到票數一瞬間與點擊買票的一瞬間實際上剩余的車票數量發生了變化!因此買票時候會再次檢查余票。如下圖,雖然紅框內同時發生,不過你網速手速不行......
所以,你看到有票但是買時候沒票
3.上百萬人同時訪問一個網站呢?
基本與上邊步驟都一樣,不過網站后臺把用來給用戶看的數據庫與用來給系統改寫的數據庫拆開了。也就是說有一個(多個)數據庫專門是給用戶讀的,有一個數據庫專門是用來做加減操作的。它們之間每隔一定時間就把內容同步一次。(用來改寫的數據庫叫主庫,用來讀取的數據庫叫從庫,一般情況下主庫只有一個,從庫有很多個。主庫的數據每隔一段時間同步到從庫中)
查看票數時候只訪問從庫:還有票哇,好開心!
買票時候改成了訪問主庫:你妹!說好的有票呢!
最后:實際應用中12306流程比這個復雜的多,比如同時10人搶1張票給誰?這么大訪問量我帶寬扛不住怎么辦?由于列車太多,少一張票就會影響整個列車線,計算量太大怎么辦?40分鐘等待時間車票怎么辦?所以這里只列舉了正常情況下比較簡單的邏輯,權當一看。