過年回家搶票,12306的余票是怎麼計算的,具體的思路是什麼?
車票售賣特點,有一張車票賣出去就會影響到整個列車線的票數:北京開往廣州的一趟列車有人買了石家莊到鄭州的票,同時意味著出發點在北京-石家莊,目的地是鄭州-廣州的所有情況都會少一張票。
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分鐘等待時間車票怎麼辦?所以這裡只列舉了正常情況下比較簡單的邏輯,權當一看。


※Spring Boot中使用AOP
※MapReduce中源碼分析(map端的過程)
TAG:程序員小新人學習 |