2020国产成人精品视频,性做久久久久久久久,亚洲国产成人久久综合一区,亚洲影院天堂中文av色

分享

對(duì)于12306,我的完整技術(shù)方案

 freezn 2012-01-18
12306主要就是賣票比較復(fù)雜,注冊(cè)登錄之類的功能就不說了。

有網(wǎng)友說,12306賣票系統(tǒng)比航空復(fù)雜,因?yàn)橐侄钨u,航空只有起點(diǎn)和終點(diǎn),火車中間還有好多站。不過好消息是,這些站在售票時(shí)是連續(xù)的,不會(huì) 出現(xiàn)1張票跳著站買的情況,這樣就可以把一張票拆成N張只有起點(diǎn)和終點(diǎn)的票,和航空售票一樣了。(我不了解航空售票,也不了解火車售票業(yè)務(wù)具體模型,下面 都是基于推測(cè)和假設(shè)之類的。)

賣票分為兩部分,查詢和購買。12306目前提供了單獨(dú)的查詢,我覺得這個(gè)其實(shí)挺好的,至少有讀寫分離的思想;不過延遲10分鐘的數(shù)據(jù),肯定沒什 么人愿意用,大家還是要擠進(jìn)購買系統(tǒng)查詢。單獨(dú)的查詢相當(dāng)于擺設(shè)了,沒有發(fā)揮作用。要讓查詢系統(tǒng)有效,尤其是春運(yùn)期間,延遲應(yīng)該在30秒之內(nèi)。

查詢剩余票數(shù)設(shè)計(jì):

查詢的特點(diǎn)是按照車次信息或者時(shí)間查,車次和時(shí)間一般都不會(huì)變,因此在設(shè)計(jì)時(shí),可以把頁面分成兩部分。一是匹配的車次列表信息,如北京到上海有哪 些車,這個(gè)結(jié)果可以用CDN緩存。車次基本是固定的,緩存設(shè)置為10分鐘應(yīng)該就能滿足需要。不占用負(fù)載。在瀏覽器拿到這個(gè)頁面后,通過異步請(qǐng)求,根據(jù)每趟 車的編號(hào)二次查詢剩余票數(shù)等實(shí)時(shí)數(shù)據(jù),合并顯示。

車次查詢時(shí),把車次信息分庫存儲(chǔ),并作冗余存儲(chǔ)。好比這個(gè)庫提供所有北京->xxx的查詢,這個(gè)庫提供上海到xxx的查詢,這個(gè)庫提供廣州 到xx的查詢,剩下的在一個(gè)大庫中等。車次變化很小,庫可以分散存,而且可以冗余存儲(chǔ)。用內(nèi)存表也行,總數(shù)據(jù)量也不多,性能上沒什么可說的。

對(duì)于實(shí)時(shí)票數(shù),確實(shí)是比較困難的,網(wǎng)上很多方案都不對(duì),沒有考慮中間站的問題。剩余票數(shù)緩存并不好做。我的想法是,提前分好票,然后用單獨(dú)的數(shù)據(jù)結(jié)構(gòu)做緩存。

例如,對(duì)于G113高鐵,共有8站:北京、德州、濟(jì)南、徐州、南京、常州、蘇州、上海。假設(shè)它有兩千張票,座位啊臥鋪啊啥的。在發(fā)票前,創(chuàng)建新表 20120113_G113,然后把2000張票提前插入到表中,每個(gè)票都有一個(gè)本表內(nèi)唯一的數(shù)字編號(hào)。表結(jié)構(gòu)基本上就是:編號(hào)、起始站、終點(diǎn)站、座位類 型、車廂、座位號(hào)、乘客姓名、乘客證件號(hào)碼、車票狀態(tài)等實(shí)際業(yè)務(wù)模型需要。初始化時(shí),起點(diǎn)站就是北京(根據(jù)順序存儲(chǔ)為1),終點(diǎn)站就是上海(根據(jù)順序存儲(chǔ) 為8),乘客信息空著表示尚未綁定乘客,車票狀態(tài)置為“待出售”。

這樣我們要查詢2012年1月13號(hào)G113 濟(jì)南->南京 的剩余票數(shù)時(shí),就查詢20120113_G113起始站編號(hào)大于等于3并且小于等于5,并且狀態(tài)為“待出售”的記錄數(shù)就行了。

每張表2000條數(shù)據(jù),對(duì)于非春運(yùn)時(shí)節(jié),性能完全足夠。對(duì)于春運(yùn)時(shí)節(jié),非繁忙路段,性能應(yīng)該也足夠了。對(duì)于春運(yùn)繁忙期,繼續(xù)看下面的。

車票出售基本流程:

用戶選擇車票并要求購買,系統(tǒng)鎖定票并標(biāo)記狀態(tài)為“鎖定中”,讓用戶付款等。完成后標(biāo)記車票為“已經(jīng)發(fā)售”,并且更新用戶信息到車票的持有人信息字段中。此票不再出售。

對(duì)于中間站購票,假設(shè)用戶購買了 濟(jì)南->南京 ,前面流程不變。但完成出票后,將車票起始和終點(diǎn)站改為“濟(jì)南”和“南京”,并且自動(dòng)插入兩張新票可用。一張是“北京->濟(jì)南”,一張是“南京 ->上?!保ㄖ?duì)列更新相關(guān)緩存。相當(dāng)于車票做了自動(dòng)分裂。這樣我們?cè)O(shè)計(jì)時(shí)只需要把一張票設(shè)計(jì)為“只有起點(diǎn)和終點(diǎn)”就行了。

更高效的剩余票數(shù)查詢?cè)O(shè)計(jì):

數(shù)據(jù)庫的count操作并不快,因此對(duì)于繁忙季節(jié)的繁忙表,每次都count是鐵定不行的。我想到的一個(gè)辦法是:把上面提到的預(yù)售車票表加載到內(nèi)存中。我們用一個(gè)64位long類型數(shù)字表示一張車票,每趟車的每種座位類型是一個(gè)long數(shù)組。

對(duì)于每個(gè)long數(shù)字,前面的32位用來順序存儲(chǔ)32個(gè)車站(假設(shè)一趟車最多有32個(gè)站,沒查過,不行可以放長(zhǎng)點(diǎn)),每一位標(biāo)記“車票是否包含此 站”。如G113 濟(jì)南到南京的票(車站順序?yàn)榈?到第5站),long數(shù)字的第2到第4位設(shè)置為1,其他前32位設(shè)置為0。后面的32位用來表示車票在車票出售表中的唯一 編號(hào)。這樣根據(jù)一個(gè)long類型數(shù)字,我們就能表述一張票的發(fā)售信息了。

比如2012年1月13號(hào)G113,有軟臥500張和硬臥1500張。那就需要兩個(gè)數(shù)組。20120113_G113_軟臥 對(duì)應(yīng)一個(gè)長(zhǎng)度500的long數(shù)組;20120113_G113_硬臥 對(duì)應(yīng)一個(gè)長(zhǎng)度1500的long數(shù)組。存儲(chǔ)所有售票信息。

有點(diǎn)類似BitSet的感覺,對(duì)空間要求不高。我們可以做個(gè)系統(tǒng)把所有車票信息按照這種結(jié)構(gòu)加載到內(nèi)存中。對(duì)于實(shí)時(shí)查票,如查詢2012年1月 13號(hào)G113車次 濟(jì)南->南京 的余票,就是遍歷兩個(gè)數(shù)組,檢查位數(shù)為2和4的long數(shù)字有多少個(gè),就直接獲得了軟臥和硬臥的剩余票數(shù)。對(duì)于現(xiàn)代計(jì)算機(jī),這點(diǎn)遍歷,時(shí)間是納秒級(jí)的。

當(dāng)車票被出售后,從long數(shù)組中刪除票信息,比如先置為-1表示已經(jīng)無效。再用后臺(tái)線程實(shí)際刪除(避免寫沖突,將刪除延遲到重建一個(gè)數(shù)組所消耗 的多少納秒內(nèi)剛好沒有寫請(qǐng)求的時(shí)間段中)。如果long數(shù)組長(zhǎng)度為0,那就是沒有車票了,直接返回0;用戶再怎么刷,也不會(huì)干擾數(shù)據(jù)庫。

更高效的剩余票數(shù)查詢方案的擴(kuò)展性和容錯(cuò)性:

本身車票是按照車次劃分的,同時(shí)也有時(shí)間維度,橫向擴(kuò)展不存在任何問題。

long數(shù)組可以根據(jù)數(shù)據(jù)庫票務(wù)信息重新構(gòu)造,而且成本不高(一條“select * from xxx where 狀態(tài)=待發(fā)售” SQL語句)。在硬件故障,擴(kuò)容機(jī)器,或是發(fā)現(xiàn)數(shù)據(jù)不一致時(shí),重新構(gòu)造數(shù)組就行。而且可以從后臺(tái)異步做。擴(kuò)展性和容錯(cuò)性都不是問題。

售票交易與鎖票:

用戶查詢到有票后,填寫要購買的票數(shù),提交。好比購買兩張硬臥,流程如下:

1. 在20120113_G113_硬臥long數(shù)組中隨機(jī)獲取符合要求的順序的兩個(gè)long數(shù)字,并將其從數(shù)組中刪除;這個(gè)速度很快,納秒級(jí);

2. 根據(jù)long數(shù)字后32位,從數(shù)據(jù)庫中鎖票。如果全部鎖定成功,設(shè)置票為預(yù)定狀態(tài),更新用戶預(yù)定信息,鎖票時(shí)間等。然后記錄日志等其他相關(guān)操作。如果鎖票 失敗,說明在納秒級(jí)的時(shí)間內(nèi),票還是有沖突,購票失敗,直接返回報(bào)錯(cuò)。鎖票就是數(shù)據(jù)庫行鎖,sql中的 select for update nowait。

3. 頁面提示錯(cuò)誤,或者進(jìn)入下一步交易流程,如網(wǎng)銀支付等。

在整個(gè)過程中,我們看到,用戶請(qǐng)求就算集中爆發(fā),事務(wù)的沖突性也能降低到“隨機(jī)獲取的long數(shù)組值剛好一樣 + 在cpu執(zhí)行2000個(gè)for循環(huán)的可能百萬分之一秒內(nèi)剛好同時(shí)提交”。我覺得沖突概率應(yīng)該很低很低。一趟車2000個(gè)車票,1:100比例也就20萬人 同時(shí)搶,20萬人同1秒提交cpu也算的過來。而實(shí)際上,怎么可能一秒鐘有20萬人同時(shí)搶一趟車的票哪……

在整個(gè)過程中,大部分請(qǐng)求都被long數(shù)組消耗完后,直接檢查long數(shù)組長(zhǎng)度為0,提示無票攔截。進(jìn)入數(shù)據(jù)庫階段的,也就是比實(shí)際的票數(shù)多一點(diǎn)點(diǎn)的有效訂單而已。

回票:

中間站買票的,在預(yù)定成功后,車票自動(dòng)分裂,分裂的票可以通過隊(duì)列調(diào)度實(shí)時(shí)的回到long數(shù)組中,繼續(xù)服務(wù)。

預(yù)定后不買的,可以通過預(yù)定時(shí)間的超時(shí)檢查,后臺(tái)做個(gè)線程,讓票回歸。

歡迎討論。

微博:http://weibo.com/guzzframework

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多