我設計的12306

feed系統和火車票售賣系統是2個高訪問高併發狀況下具體很大挑戰的系統。
在低訪問,低併發的狀況下feed系統會變的很是簡單,數據模型和業務功能都比較容易設計和實現,主要的挑戰就剩如何面對層出不窮的敏感詞和花樣百出的廣告語。相比之下,火車票售賣系統在低併發時也頗有趣,假設我是12306的架構師,我會如何設計12306那。前端

數據模型

先將系統進行拆分,獨立成用戶,車票,下單3個系統,每一個系統內部封閉成多個服務,運行在獨立的集羣上面。這裏只對車票系統進行數據模型設計。數據庫

先上ER圖 數據模型緩存

數據分紅動靜2部分,車次,站點,座位的數據都是靜態的基本不會變,能夠經過運營系統提早進行錄入生成;車票則根據以上三張表天天動態生成,每條車票記錄一個車次上的一個座位號,初始化的始發站,終點站爲該車次的始發站和終點站,數據在下單時進行更新。肯定了數據模型後進行數據庫的垂直和水平拆分,首先按照車次進行分庫,將不一樣的車次hash到幾個數據庫中,減小每一個數據庫的負載;而後車票表按天拆分,提早生成3個月的車票表,每張車票表只存儲當天發車的車票。性能優化

用例

  • case1:查詢
    假設有一列從北京到深圳的火車D911,途經共20站。用戶查詢北京到杭州的列車,從cache中取出符合用戶查詢條件的車次(車次類型,始發站,終點站,始發時間,到站時間),按照車次從cache中取出北京和杭州的站點id和站序,北京站序爲0,杭州站序爲11。車票表中用
    ‘始發站序<=0 and 終點站序>=11 and 車次=D911 group by 座位類型’
    的查詢條件便可獲得每種座位的剩餘票數,能夠將查詢的結果作一個10s的緩存,若是前端展現的不是具體的剩餘票量,而是有無票,可使用一個更長時間的緩存,緩存的失效由服務端控制。
  • case2:車票分拆
    假設有一列從北京到深圳的火車D911,用戶購買了一張從北京到杭州的車票,按照規則優先級隨機取出一張車票,車票數據爲 北京-深圳,始發站序0,終點站序20,將該車票狀態置爲無效,插入一張數據爲杭州-深圳,始發站序11,終點站序20的車票,向下單系統發起請求,寫入一張北京-杭州的訂單。
  • case3:車票合併
    假設有一列從北京到深圳的火車D911,用戶預訂了北京-杭州的車票,從下單系統收到該訂單失敗或者超時或者退票的消息,取出其中和車票相關的信息,車次D911,北京-杭州,始發站序0,終點站序11,和車票表中該車次該座位的數據進行關聯,合併數據,從新生成一條北京-深圳的車票。

隊列·流控·異步·無鎖實現

系統的抗壓能力和是吞吐量成正比的,這也就是爲何靜態頁面能夠支持超高的QPS,查詢的性能優化也比較容易,事務處理的性能提高最困難,系統處理時會保持tcp連接,佔用系統資源,最終致使系統的崩潰,響應時間越快,資源的佔用時間越短,吞吐能力也就越強,系統的可用性也就越高。
在某寶某貓作話費充值系統的思路徹底能夠用來作火車售票系統,將下單請求持久化,系統間經過消息解耦,經過多線程隊列異步處理請求。具體的實現能夠在收到下單購票請求後持久化,返回給用戶一個排隊中的提示(1-x分鐘處理完成),按照車次放到不一樣的隊列中進行排隊(期間能夠作過濾/去重/合併處理),系統從隊列中取數據進行處理。最終一致性就能夠知足業務需求的地方,服務儘可能減小事務和鎖的使用,提升併發處理能力。多線程

降級

爲啥要把降級單獨拉出來講,我以爲本質上講降級並非因爲架構設計上的充分考慮帶來的可用性和伸縮性的提升,而是犧牲一部分的用戶體驗換來的系統的可用性,是對峯值事件的應對策略。基本實現就是在系統埋好各類開關,能夠由人工控制也能夠由系統觸發,保證最基本的核心功能可用,其餘的非核心功能和部分用戶體驗能夠暫時捨棄。架構

數據模型和業務功能就是這樣,不論實現的多扭曲基本上你們均可以作出來,功能實現以後無bug是一個挑戰,可以知足將來變化是一個挑戰,在某個量級以後依然可用又是一個挑戰。併發

相關文章
相關標籤/搜索