知乎專欄 | 多維度架構 | 微信號 netkiller-ebook | QQ群:128659835 請註明“讀者” |
軟件的設計都要圍繞着災備進行,不能分散式運行,就不合格。
交易軟件通常使用TCP私有協議,與我們常見的HTTP協議不同,HTTP是無狀態,即用戶請求-處理數據-渲染HTML頁面-銷毀並釋放內存,我們很容易開發基于負載均衡的橫向水平擴展的應用程序。 而交易軟件採用的是持久TCP連接,實時傳輸用戶請求,並將結果會送給用戶,中間過程不允許中款,且用戶狀態數據存儲在該交易伺服器的內存中,如果我們採用常規手段做負載均衡,就會出現用戶被分配到另一台伺服器上,而無法繼續交易。
我們首先要做的就是將用戶狀態持久化,有點類似我們在HTTP應用中將Session持久化方法,將這些數據存儲到公共的共享伺服器上。同時該伺服器也需要做高可用等等,保證無單點故障。
第二步,我們解決分散式交易,分散式交易是指可以在交易伺服器上任意一個節點上均可交易。方法有很多,複雜程度也不同。
通常解決分散式運行的方法,無非是同步|互斥排他鎖|共享存儲等等,其實就是兩多綫程的很多技術擴展到了互聯網上。使用節點同步解決共享內存訪問問題,使用遠程鎖解決解決多節點訪問問題等等。
解決掛單問題,通常交易是即時完成的,較難處理的就是掛單。
下面的方案是最簡單的,開發難度最低。
資料庫表中增加一個欄位例如
----------------------------------------- Id | node | status | xxxxx ----------------------------------------- 1 | trader1 | N | xxxxx 2 | trader2 | Y | xxxxx -----------------------------------------
trader1 表示該記錄產生在trader1 必須在Trader 1上完成成交
trader2 表示該記錄產生在trader2 必須在Trader 2上完成成交
測試用例
提示 | |
---|---|
更新記錄狀態必須增加node條件 |
Update tab set status=Y where id=1 and node =<my node> …
雙向通知的含義是Trader 1狀態發生改變會通知Trader 2, 反之Trader 2狀態發生改變會通知 Trader 1。
上圖可以看出通知與資料庫持久關係圖,在交易周期內實時接收通知,一旦收到通知,便根據通知中的指令做出反應,改變當前交易伺服器的狀態。
這種設計可以採用日誌複製,然後重做日誌的方式,非常累西資料庫同步技術,缺點是可能有延遲。設計需要考慮進去。如果超過三個節點就要採用環形複製
我曾經想過通過IP組播,廣播技術實現通知發佈,這樣就可以不設置目的地地址,同時增加了部署的靈活性,而且對於廣播節點數量沒有限制。比較適合三個以上的機房部署。
用戶分流是指,不同用戶登錄到不同的伺服器上進行交易。因為我們的交易系統是可以水平擴展的,可以有很多台交易伺服器並且都是Active狀態,任意一台伺服器都能登陸交易,我們可以使用哈希算法基于用戶ID,將用戶分流到指定伺服器。
用戶分流還可以使用智能DNS技術,將用戶分流到距離自己最近的交易伺服器上。
還可以根據路由TTL值與Ping值進行優先順序分配。
我們這個行業不是門戶網站,所以數據量不會非常大,但我們要未雨綢繆,我們在設計階段就將這些問題考慮進去,使將來不會困擾我們。
數據量最大的當屬交易數據,有些金融產品雙向交易,交易時間長,所以交易數據的累積相當可觀。
雖然你可以定時刪除,但我不建議。我認為交易數據需要永久保留,為什麼? 當交易數據積累到一定數量級,我們就可以從多角度數據挖掘,為決策提供數據支持。
當數據龐大到無論怎麼優化都無法提高查詢性能是,這時你就要考慮資料庫拆分了。
資料庫拆分需要遵循幾個原則,不僅僅是按照年份或月份分庫分表。
資料庫拆分
傳統方法,將數據日期切分,這回帶來索引的不連續問題,且查詢時必須加帶日期,以便定位到指定的表中。如果需要做數據挖掘,需要統計四年的數據,必須查詢四次,效率大打折扣。
新的拆分方案,通過哈西算法均勻的將用戶分配到指定資料庫中或表中。這樣所有針對該用戶的操作都能在同一個資料庫中完成。
根據不同的功能拆分資料庫或表,也是一種非常不錯選擇。