如何構建一個交易系統(tǒng)(十一)

天下武功唯不破国觉,那么對于交易系統(tǒng)更是如此,如何達到這個快痕寓,可以提升單機性能针饥,提高運算速度和效率丁眼, 可以橫向集群擴展增加吞吐量和并行能力昭殉。盡可能將數(shù)據(jù)放在內存, 在內存中實現(xiàn)計算是一種行之有效的方法挪丢,IMDG(In Memory Data Grid), 是此篇我們將要探討的內容。

概述

需求
對于一個交易系統(tǒng)惠啄,在交易時段撵渡,需要非常精確快速提供下面幾點服務:

  1. 保存和計算所有用戶的資金信息
    1. 可用現(xiàn)金
    2. 占用保證金
    3. 賬戶浮動盈虧
    4. 實時聚合計算死嗦,規(guī)則引擎觸發(fā)
  2. 保存和計算用戶持倉
    1. 倉位變更
    2. 實時浮動盈虧計算
  3. 實時消息推送
    1. 用戶在線狀態(tài)
    2. 訂閱價格信息
    3. 持倉倉位信息

基本條件

我們需要這樣一個工具(或者服務)提供:

  1. 緩存
  2. 內存中索引
  3. 高可用性
  4. 易擴展性
  5. 落地方案
  6. 流式計算
  7. 內存運算
In Memory Data Grid

當建立一個大型Java應用時越除,引起性能問題大部分是延遲,在一個分布式Java系統(tǒng)中引起延遲的原因可能有:

  1. 從磁盤上加裝數(shù)據(jù)的IO延遲
  2. 跨網絡加裝數(shù)據(jù)的IO延遲
  3. 在分布式鎖上的資源爭奪
  4. 垃圾回收引起的暫停(在JAVA 應用中這個尤為重要)

典型Ping時間是:本地機器是57μs翼雀;局域網是300 μs狼渊;從倫敦到紐約是100ms;對于1Gb網絡坦弟,網絡數(shù)據(jù)傳輸是每秒 25MB – 30MB酿傍。對于10GB網絡是每秒250MB – 350MB驱入。使用SATA 3.0接口的SSD硬盤數(shù)據(jù)傳輸是每秒500-600MB亏较。如果你有1G以上數(shù)據(jù)需要處理,磁盤延遲會嚴重影響應用性能遵岩。

硬件上最低延遲是內存巡通,典型的內存緩存是每秒3-5 GB宴凉,能夠隨著CPU擴展。如果你有兩個處理器丧靡,你就能每秒10GB籽暇,如果有4CPU就能獲得 20GB. 有一個內存基準測試稱為STREAM 是測試許多計算機的內存吞吐量图仓,一些在大量CPU幫助下能夠實現(xiàn)每秒TB級別的吞吐量救崔。

在內存中存放和管理數(shù)據(jù)是降低延遲最有效的方法之一捏顺,現(xiàn)如今內存的價格大大的下降幅骄,現(xiàn)在幾十G的上T的服務器非常常見本今, 使得這樣的操作方法的以可行冠息; 內存中保證高可用性, 勢必涉及partition 和 replication, 分布式計算躏碳、backup散怖, 再平衡等等镇眷, 和外圍語言的交互欠动,借用ignite 圖大概這個樣子:

一個內存網格工具需要具備功能

IMDG 提供一個完全基于內存的架構, 理論上可能給你應用提升幾倍或者幾十倍的性能提升铆遭, 可以將上T的數(shù)據(jù)載入內存, 能夠很好滿足現(xiàn)如今大數(shù)據(jù)處理的需求啼肩。

IMDG, 直觀可以認為是一個分布式的hash map, 你按照key 存儲數(shù)據(jù)衙伶, 和傳統(tǒng)的系統(tǒng)不一樣矢劲,key, value 必須是一個string 或者byte數(shù)組, 你可以直接用你領域對象作為key 和 value躺同,不需要序列反序列化這些對象將給你的業(yè)務處理流程帶來大量的編輯蹋艺, 使用和操作這里map 就和你處理本地的hash map 一樣,這個特征也是IMDG, 和IMDB(In-Memory Database)區(qū)分民效, 省去ORM不僅僅省去很多不必要的麻煩涛救,也會有性能上的提升检吆。

IMDG和其他一些產品, 比如NoSql, IMDB, NewSql 數(shù)據(jù)庫交煞,一個現(xiàn)在的區(qū)別就是使用集群, IMDG可以按照partition將數(shù)據(jù)replicate 和均勻的分布在你網絡節(jié)點中斟或, 所以理論上網絡節(jié)點越多萝挤,能夠存儲的數(shù)據(jù)就越多怜珍。在IMDG 使用需要注意點,應該讓你的運算盡量靠近數(shù)據(jù)--類似于Map-Reduce, Hadoop 中思想今豆, 因為在網絡世界中呆躲,移動計算比移動數(shù)據(jù)更省事捶索,當整個網絡拓撲圖穩(wěn)定后,大部分時間數(shù)據(jù)是待在固定的節(jié)點箩祥, 只有在加入肆氓,或者有節(jié)點退出情況下谢揪,產生re-partition 才會導致數(shù)據(jù)在節(jié)點的移動。

Partition & Replication

在我們的運用中有一個必不可少的步驟,就是數(shù)據(jù)持久化患民,將數(shù)據(jù)存儲到外部界質匹颤,下圖的ignite使用方法,這里也可以實現(xiàn)自己的cache storage, 比如通過write/read through保存到數(shù)據(jù)庫印蓖。

緩存落地

分布式計算是通過以并行的方式執(zhí)行來獲得高性能赦肃、低延遲和線性可擴展。在集群內的多臺計算機上執(zhí)行分布式計算和數(shù)據(jù)處理船侧。分布式并行處理是基于在任何集群節(jié)點集合上進行計算和執(zhí)行然后將結果返回實現(xiàn)的镜撩。

內存計算

上面是根據(jù)我們業(yè)務場景琐鲁, 需要基于內存的解決方案人灼, 最終選擇 apache ignite作為IMDG解決方案投放, 當然業(yè)界有很多其他的IMDG 產品比如:

  1. Hazelcast
  2. Gemfire
  3. Coherence 當年還是tangosol 用過
  4. Ehcache
  5. Terracotta

實踐

PNL

PNL分基本兩種: 一種是浮動灸芳, 一種是結算好的;結算好的比較好理解冯遂, 一個買賣周期結束蛤肌,錢已落袋就是最終的盈虧批狱,這個是固定不變的赔硫,另外一種是浮動爪膊, 在每個價格跳動都要計算一次, 結算好的PNL在實現(xiàn)方法上面沒有太大的挑戰(zhàn)僵芹, 同時他的TPS 也相對平緩拇派, 但是對于浮動PNL凿跳, 特別在像外匯交易中控嗜,計算的強度非常的大, 幾乎每秒都有3~5個以上的報價曾掂, 同時如果用戶有大量的持倉珠洗。 對系統(tǒng)有運算能力有巨大的挑戰(zhàn)若专。

實時計算

首先要做的就是將用戶的持倉信息載入內存膊爪,分布于集群中, 對于計算的頻次沛豌,也有有區(qū)分, 這個根據(jù)不用用戶的持倉比(占用保證金率)赃额, 對于占比高的(70%以上)的當然需要更頻繁的計算加派, 對于低比例比如小于30%,其實這樣的倉位非常安全爬早,適當擴大計算的頻次風險比較低哼丈, 當然也要根據(jù)價格波動的區(qū)間, 價格波動非常大時候筛严, 需要整體的計算一遍醉旦。

一旦訂單match后會通過ESB(Kafka,Redis) 推送到PNL節(jié)點,由于用戶的持倉是多節(jié)點集群桨啃,在replication 模式下保持3個backup; 每個節(jié)點有自己的primary partition, 同時使用Kafka 在publish 時使用同樣的partition 算法分發(fā)到Kafka topic partition中,這樣保證每個集群中節(jié)點只consume 自己primary partition 上面的數(shù)據(jù)照瘾, 大大減少了數(shù)據(jù)在節(jié)點間的re-balance; 但是這里需要自己監(jiān)聽持倉cache 上面的EVTS_CACHE_REBALANCE 消息匈棘; 這會額外增加節(jié)點間的通訊量, 但是基于析命,一般集群拓撲圖穩(wěn)定后很少變動主卫, 這點損耗還是值得的。

浮動PNL能否正確無誤的計算出來鹃愤, 對于下游一系列的模塊正常運作非常重要簇搅。

規(guī)則引擎

在整個交易系統(tǒng)中, 涉及規(guī)則的地方非常多软吐, 簡單比如什么時候margin call? Stop 條件的觸發(fā)瘩将, 在開市時間需要實時的觸發(fā), 有兩種方法凹耙, 一種是被動姿现,定時Job去掃描; 另外一種是主動在變動數(shù)據(jù)上面加上監(jiān)聽條件 reactive callback 回來肖抱。 對于margin call,的觸發(fā)可以使用Job 定時比如1分鐘去掃描备典; 而對于stop 規(guī)則 需要使用continuous query 這樣的功能在價格和變動后,立刻執(zhí)行虐沥。

規(guī)則引擎

微服務

對熊经, 我們這里也用到了時髦的微服務泽艘,這里也是借助ignite 的服務網格來注冊和發(fā)現(xiàn)和部署服務欲险, 只不過我們這里用到 DDD 開發(fā)模式镐依, 對于一個聚合根的變動,原則在一個時間點只能在一臺機一個線程中處理天试,所以這里需要做些額外的處理槐壳, ignite 可以根據(jù)NodeFilter 條件來選擇用集群中的某個節(jié)點上的服務, 因為可能這個節(jié)點有你服務依賴的數(shù)據(jù)喜每, 而對于我們的DDD务唐,這個是個必要條件, 必須在每個固定的節(jié)點带兜,除非這個節(jié)點從primary 角色退出枫笛; 這里涉及到微服務發(fā)現(xiàn)的方式, 可以參考Pattern: Service registry刚照。

微服務

我們的做法是使用Client 發(fā)現(xiàn)服務的方式枪眉,在分兩種接癌, 一種是偶爾需要定位某個服務類似ad-hoc, 現(xiàn)用現(xiàn)查,另外一種是和某項服務有長期的關聯(lián)炮叶, 比如一個book 和我們portfolio 管理模塊, 這個時候需要注冊服務提供節(jié)點網絡拓撲圖改變listener拾积,隨時保持保持最新更新抹蚀, 或者退而求其次,設置一個重試機制郭变,在錯誤達到一個benchmark, 再重新定位服務颜价。

風控

風險監(jiān)控, 包含margin call, 某些交易規(guī)則觸發(fā)诉濒, 如頭寸大小是否超過設定benchmark, 這里借助ignite continuous query + redis , 以 Realtime 處理周伦。

風險和監(jiān)控

風險還包括 fault detection 這些部分以Near realtime處理,可以借助 ELK循诉、和NEO4J 類似工具來完成横辆。

Market 數(shù)據(jù)

市場數(shù)據(jù), 涉及 realtime 和 history 數(shù)據(jù)茄猫; 其實按照價格傳播的快慢可以分幾大類型價格:

  1. 匹配中心狈蚤, 這個是最新最快價格放在節(jié)點的本地 hashmap 中
  2. 內部計算的價格,通過redis 發(fā)送給PNL划纽, Account 節(jié)點
  3. 歷史數(shù)據(jù)脆侮,比如分時,小時這個是最后價格勇劣,通過KAFKA 到Market 節(jié)點進行聚合和存儲
時序數(shù)據(jù)

在考察了一堆的時序數(shù)據(jù)庫靖避,比如最近當紅炸子雞InfluxDB,但是如何處理OHLC潭枣,特別在你有10來個價格檔位情況下沒有看到合適的處理方法,同時InfluxDB 開源不支持集群了幻捏。 通過簡單的評估盆犁, 比如平均有200產品同時開市,每個每秒平均報價5次篡九, 有10種K線聚合情況下谐岁, 每秒其實也就 200x5x10 ~= 10000 次操作, 如果完全在內存中還是綽綽有余榛臼,DONE伊佃!

所以很多時候解決方案,沒有你想像那么復雜沛善, 計算機沒有你想像那么快航揉,也沒有你想像那么不堪,只有試過方知可不可金刁。

Market 數(shù)據(jù)部分同時涉及帅涂,報價往客戶端實時發(fā)送, 這里涉及內容比較多胀葱,下篇再說漠秋。

上面涉及的各模塊之間的交互,其實不完全借助IMDG完成抵屿,KAFKA在內部消息通道中占有很大一塊比重庆锦,將分獨立篇幅敘述。

參考

  1. 為什么要使用數(shù)據(jù)網格Data Grid
  2. 開源數(shù)據(jù)網格平臺Infinispan訪談
  3. In-Memory Data Grids
  4. From Cache To In-Memory Data Grids
  5. In-Memory Database vs. In-Memory Data Grid: Revisited
  6. in-memory data grid
  7. In-Memory Data Grid: Explained
  8. Apache Ignite(V2.3.0)中文開發(fā)手冊
  9. Top 15 In Memory Data Grid Platform
  10. apache ignite 是什么東西轧葛,最近勢頭很猛搂抒?

GoXTX 下一代交易平臺技術供應商
GoXTX one-stop solution for neXT generation eXchange

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市尿扯,隨后出現(xiàn)的幾起案子求晶,更是在濱河造成了極大的恐慌,老刑警劉巖衷笋,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件芳杏,死亡現(xiàn)場離奇詭異,居然都是意外死亡辟宗,警方通過查閱死者的電腦和手機爵赵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來泊脐,“玉大人空幻,你說我怎么就攤上這事∪菘停” “怎么了秕铛?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵约郁,是天一觀的道長。 經常有香客問我但两,道長鬓梅,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任镜遣,我火速辦了婚禮己肮,結果婚禮上士袄,老公的妹妹穿的比我還像新娘悲关。我一直安慰自己,他們只是感情好娄柳,可當我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布寓辱。 她就那樣靜靜地躺著,像睡著了一般赤拒。 火紅的嫁衣襯著肌膚如雪秫筏。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天挎挖,我揣著相機與錄音这敬,去河邊找鬼。 笑死蕉朵,一個胖子當著我的面吹牛崔涂,可吹牛的內容都是我干的。 我是一名探鬼主播始衅,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼冷蚂,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了汛闸?” 一聲冷哼從身側響起蝙茶,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎诸老,沒想到半個月后隆夯,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡别伏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年蹄衷,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片畸肆。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡宦芦,死狀恐怖,靈堂內的尸體忽然破棺而出轴脐,到底是詐尸還是另有隱情调卑,我是刑警寧澤抡砂,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站恬涧,受9級特大地震影響注益,放射性物質發(fā)生泄漏。R本人自食惡果不足惜溯捆,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一丑搔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧提揍,春花似錦啤月、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至刨仑,卻和暖如春郑诺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背杉武。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工辙诞, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人轻抱。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓飞涂,卻偏偏與公主長得像,于是被迫代替她去往敵國和親十拣。 傳聞我的和親對象是個殘疾皇子封拧,可洞房花燭夜當晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內容