Home | 簡體中文 | 繁體中文 | 雜文 | 知乎專欄 | Github | OSChina 博客 | 雲社區 | 雲棲社區 | Facebook | Linkedin | 視頻教程 | 打賞(Donations) | About
知乎專欄多維度架構 微信號 netkiller-ebook | QQ群:128659835 請註明“讀者”

14.5. 軟件開發

軟件的設計都要圍繞着災備進行,不能分散式運行,就不合格。

14.5.1. 交易軟件分散式交易

交易軟件通常使用TCP私有協議,與我們常見的HTTP協議不同,HTTP是無狀態,即用戶請求-處理數據-渲染HTML頁面-銷毀並釋放內存,我們很容易開發基于負載均衡的橫向水平擴展的應用程序。 而交易軟件採用的是持久TCP連接,實時傳輸用戶請求,並將結果會送給用戶,中間過程不允許中款,且用戶狀態數據存儲在該交易伺服器的內存中,如果我們採用常規手段做負載均衡,就會出現用戶被分配到另一台伺服器上,而無法繼續交易。

我們首先要做的就是將用戶狀態持久化,有點類似我們在HTTP應用中將Session持久化方法,將這些數據存儲到公共的共享伺服器上。同時該伺服器也需要做高可用等等,保證無單點故障。

第二步,我們解決分散式交易,分散式交易是指可以在交易伺服器上任意一個節點上均可交易。方法有很多,複雜程度也不同。

通常解決分散式運行的方法,無非是同步|互斥排他鎖|共享存儲等等,其實就是兩多綫程的很多技術擴展到了互聯網上。使用節點同步解決共享內存訪問問題,使用遠程鎖解決解決多節點訪問問題等等。

14.5.1.1. 分散式交易解決方案一

解決掛單問題,通常交易是即時完成的,較難處理的就是掛單。

下面的方案是最簡單的,開發難度最低。

資料庫表中增加一個欄位例如

-----------------------------------------
Id  | node | status | xxxxx
-----------------------------------------
1 | trader1 | N | xxxxx
2 | trader2 | Y | xxxxx
-----------------------------------------
				

trader1 表示該記錄產生在trader1 必須在Trader 1上完成成交

trader2 表示該記錄產生在trader2 必須在Trader 2上完成成交

測試用例

  1. Trader1 上登陸,下單,然後退出
  2. 在Trader2 上登陸如果1 | trader1 | xxxxx 沒有成交,將node 改為 trader2 同時將掛單數據載入到Trader2伺服器的內存中。
  3. Trader1 的中的掛單將失效
  4. 如果登陸Trader2前1 | trader1 | xxxxx 已經成交,就放棄載入內存。
[提示]提示
更新記錄狀態必須增加node條件
				
Update tab set status=Y where id=1 and node =<my node> …
				
				

14.5.1.2. 分散式交易解決方案一

雙向通知的含義是Trader 1狀態發生改變會通知Trader 2, 反之Trader 2狀態發生改變會通知 Trader 1。

圖 14.7. 雙向通知解決方案

雙向通知解決方案

上圖可以看出通知與資料庫持久關係圖,在交易周期內實時接收通知,一旦收到通知,便根據通知中的指令做出反應,改變當前交易伺服器的狀態。

這種設計可以採用日誌複製,然後重做日誌的方式,非常累西資料庫同步技術,缺點是可能有延遲。設計需要考慮進去。如果超過三個節點就要採用環形複製

我曾經想過通過IP組播,廣播技術實現通知發佈,這樣就可以不設置目的地地址,同時增加了部署的靈活性,而且對於廣播節點數量沒有限制。比較適合三個以上的機房部署。

14.5.1.3. 分散式交易解決方案一

消息對列,即將所有交易伺服器接入到消息隊列中,所有通知均推送進入消息隊列,由消息隊列伺服器統一管理通知消息,同時消息具備持久化。

圖 14.8. 消息對列解決方案

消息對列解決方案

這種方法將消息交換MQ去處理,免去了自行開發消息中間件,目前MQ技術也比較成熟。

14.5.2. 交易終端

14.5.2.1. 用戶分流

用戶分流是指,不同用戶登錄到不同的伺服器上進行交易。因為我們的交易系統是可以水平擴展的,可以有很多台交易伺服器並且都是Active狀態,任意一台伺服器都能登陸交易,我們可以使用哈希算法基于用戶ID,將用戶分流到指定伺服器。

用戶分流還可以使用智能DNS技術,將用戶分流到距離自己最近的交易伺服器上。

還可以根據路由TTL值與Ping值進行優先順序分配。

14.5.2.2. 會話保持

交易終端與交易伺服器一旦連接,出現超時中斷,人為退出,下一次連接還應該上一次連接的那台交易伺服器。

如果是交易伺服器無法連接將會重新分配一台,並記錄配置

如果交易伺服器採用的是雙向通知,或者消息隊列技術,可不必記錄登陸伺服器,可能按照最小連連接數算法分配伺服器。

14.5.3. API 應用程序介面

上文反覆提到了API,關於API請參考我的另一邊文章 《CVS開發框架》 ,這裡不再引用。

圖 14.9. CVS開發框架


框架講述的設計思路,你可以使用你最熟悉語言技術重新實現。

14.5.4. 大數據的問題

我們這個行業不是門戶網站,所以數據量不會非常大,但我們要未雨綢繆,我們在設計階段就將這些問題考慮進去,使將來不會困擾我們。

數據量最大的當屬交易數據,有些金融產品雙向交易,交易時間長,所以交易數據的累積相當可觀。

雖然你可以定時刪除,但我不建議。我認為交易數據需要永久保留,為什麼? 當交易數據積累到一定數量級,我們就可以從多角度數據挖掘,為決策提供數據支持。

14.5.4.1. 第一個階分區表

第一個階段數據分區存儲,實施規劃是五年之內。五年之內你可以使用分區這種技術存儲數據。分許能夠保持索引的連續,方便複雜的資料庫查詢。

14.5.4.2. 第二個階分庫分表

當數據龐大到無論怎麼優化都無法提高查詢性能是,這時你就要考慮資料庫拆分了。

資料庫拆分需要遵循幾個原則,不僅僅是按照年份或月份分庫分表。

資料庫拆分

  1. 基于用戶拆分,要能保證查詢某個用戶的數據不需要跨庫,也不需要聯合多表查詢,這樣會降低查詢效率。
  2. 基于業務拆分,某些業務所用到的表,集中放在一台伺服器上,保證數據查詢不需要跨庫,或者聯合多表查詢。

圖 14.10. 傳統的分表方案

傳統的分表方案

傳統方法,將數據日期切分,這回帶來索引的不連續問題,且查詢時必須加帶日期,以便定位到指定的表中。如果需要做數據挖掘,需要統計四年的數據,必須查詢四次,效率大打折扣。

圖 14.11. 推薦的分表方案

推薦的分表方案

新的拆分方案,通過哈西算法均勻的將用戶分配到指定資料庫中或表中。這樣所有針對該用戶的操作都能在同一個資料庫中完成。

圖 14.12. 基于功能分表方案

基于功能分表方案

根據不同的功能拆分資料庫或表,也是一種非常不錯選擇。

14.5.5. 數據校對

由於網絡傳輸丟包和延遲等客觀情況,當交易數據量比較大且並發請求過多時,可能導致數據無法同步成功或丟失,造成兩個交易系統數據不一致。 兩個交易資料庫的數據不對等,為瞭解決該問題,可採開發一個數據校對工具,對數據進行比對和修復。確保數據一致性和完整性。