莫斯科交易所交易和清算系統架構的演變。 第1部分

莫斯科交易所交易和清算系統架構的演變。 第1部分

大家好! 我的名字是 Sergey Kostanbaev,在交易所我正在開發交易系統的核心。

當好萊塢電影展示紐約證券交易所時,它總是這樣的:人山人海,每個人都在喊著什麼,揮舞著文件,正在發生完全的混亂。 這種情況在莫斯科交易所從未發生過,因為交易從一開始就以電子方式進行,並且基於兩個主要平台 - Spectra(外匯市場)和 ASTS(外匯、股票和貨幣市場)。 今天我想談談 ASTS 交易和清算系統架構的演變,以及各種解決方案和發現。 故事很長,所以我不得不把它分成兩個部分。

我們是世界上為數不多的交易所有類別資產並提供全方位交易服務的交易所之一。 例如,去年我們的債券交易量在全球排名第二,在所有證券交易所中排名第25位,在公開交易所中排名第13位。

莫斯科交易所交易和清算系統架構的演變。 第1部分

對於專業交易參與者來說,反應時間、時間分佈穩定性(抖動)和整個綜合體的可靠性等參數至關重要。 目前我們每天處理數千萬筆交易。 系統內核處理每筆交易需要幾十微秒的時間。 當然,除夕夜的行動電信商或搜尋引擎本身的工作量比我們高,但就工作量而言,加上上述特點,在我看來,很少有人能與我們相比。 同時,對我們來說重要的是系統一秒不慢,工作絕對穩定,所有使用者都是平等的。

一點歷史

1994年,澳洲ASTS系統在莫斯科銀行間貨幣交易所(MICEX)上線,俄羅斯電子交易的歷史從此開始。 1998 年,交易所架構進行了現代化改造,引入了互聯網交易。 從那時起,所有系統和子系統中新解決方案的實施和架構變化的速度不斷加快。

那些年,交換系統運行在高階硬體上——超可靠的 HP Superdome 9000 伺服器(基於 精簡指令集計算機),其中所有內容絕對都是重複的:輸入/輸出子系統、網路、RAM(事實上,有一個 RAM 的 RAID 陣列)、處理器(可熱插拔)。 可以在不停止機器的情況下更改任何伺服器組件。 我們依賴這些設備並認為它們實際上是安全的。 作業系統是類別Unix的HP UX系統。

但從2010年左右開始,出現了一種現象,稱為高頻交易(HFT),或高頻交易──簡單地說,就是證券交易所機器人。 短短2,5年,我們伺服器的負載增加了140倍。

莫斯科交易所交易和清算系統架構的演變。 第1部分

以舊的建築和設備根本無法承受這樣的荷載。 有必要以某種方式適應。

開始

對交換系統的請求可以分為兩種類型:

  • 交易。 如果您想購買美元、股票或其他東西,您可以向交易系統發送交易並收到有關成功的回應。
  • 資訊請求。 如果您想了解當前價格,請查看訂單簿或指數,然後發送資訊請求。

莫斯科交易所交易和清算系統架構的演變。 第1部分

概括地說,系統的核心可以分為三個層次:

  • 客戶級別,經紀人和客戶在該級別工作。 它們都與存取伺服器互動。
  • 網關伺服器是本機處理所有資訊請求的快取伺服器。 您想知道俄羅斯聯邦儲蓄銀行股票目前的交易價格嗎? 該請求發送至訪問伺服器。
  • 但如果您想購買股票,則請求會發送到中央伺服器(交易引擎)。 每種類型的市場都有一個這樣的伺服器,它們發揮著至關重要的作用,我們正是為它們創建了這個系統。

交易系統的核心是一個巧妙的記憶體資料庫,其中所有交易都是交易所交易。 基礎是用 C 編寫的,唯一的外部相依性是 libc 函式庫,而且根本沒有動態記憶體分配。 為了減少處理時間,系統從一組靜態數組和靜態資料重定位開始:首先,將當天的所有資料載入到記憶體中,不再執行進一步的磁碟訪問,所有工作僅在記憶體中進行。 當系統啟動時,所有參考資料都已經排序,因此搜尋工作非常高效,並且在運行時花費的時間很少。 所有表都是用動態資料結構的侵入式列表和樹製成的,因此它們在運行時不需要記憶體分配。

讓我們簡單回顧一下我們的交易和清算系統的發展歷史。
第一個版本的交易和清算系統架構建立在所謂的Unix互動之上:使用共享記憶體、訊號量和佇列,每個進程由單一執行緒組成。 這種方法在 1990 世紀 XNUMX 年代初很流行。

系統的第一個版本包含兩層閘道器和交易系統的中央伺服器。 工作流程是這樣的:

  • 客戶端發送請求,該請求到達網關。 它檢查格式的有效性(但不檢查資料本身)並拒絕不正確的交易。
  • 如果已發送訊息請求,則在本地執行; 如果我們談論的是交易,那麼它會被重新導向到中央伺服器。
  • 然後交易引擎處理交易,修改本地存儲器,並向交易發送回應以及交易本身以使用單獨的複製引擎進行複製。
  • 網關接收中心節點的聲音並將其轉發給客戶端。
  • 一段時間後,網關透過複製機制接收到事務,這次在本地執行,改變其資料結構,以便下一個資訊請求顯示最新的資料。

事實上,它描述了一種複製模型,其中網關完全複製了交易系統中執行的操作。 單獨的複製通道確保事務在多個存取節點上以相同的順序執行。

由於程式碼是單線程的,因此使用具有進程分叉的經典方案來為許多客戶端提供服務。 然而,分叉整個資料庫的成本非常高,因此使用了輕量級服務進程,從 TCP 會話中收集資料包並將其傳輸到一個佇列(SystemV 訊息佇列)。 網關和交易引擎僅與該佇列一起工作,從那裡獲取交易以執行。 無法再向它發送回應,因為不清楚哪個服務進程應該讀取它。 所以我們採取了一個技巧:每個分叉進程為自己建立一個回應佇列,當請求進入傳入佇列時,回應佇列的標籤會立即加入其中。

不斷地將大量資料從一個佇列複製到另一個佇列會產生問題,對於資訊請求尤其常見。 因此,我們使用了另一個技巧:除了回應佇列之外,每個進程還會建立共享記憶體(SystemV Shared Memory)。 包裹本身被放置在其中,隊列中只儲存一個標籤,以便人們可以找到原始包裹。 這有助於將資料儲存在處理器快取中。

SystemV IPC 包括用於檢視佇列、記憶體和信號量物件狀態的實用程式。 我們積極地利用它來了解系統在特定時刻發生了什麼、資料包在哪裡累積、什麼被阻止等。

第一次現代化

首先,我們擺脫了單一進程閘道。 它的顯著缺點是它只能處理一個複製事務或來自客戶端的一個資訊請求。 並且隨著負載的增加,網關將需要更長的時間來處理請求,並且將無法處理複製流。 此外,如果客戶端發送了一筆交易,那麼您只需檢查其有效性並進一步轉發即可。 因此,我們用多個可以並行運行的元件取代了單一 Gateway 進程:使用 RW 鎖定在共享記憶體區域上彼此獨立運行的多執行緒資訊和事務進程。 同時我們引入了調度和複製流程。

高頻交易的影響

上述版本的架構一直存在到 2010 年。 同時,我們對HP Superdome伺服器的效能不再滿意。 此外,PA-RISC 架構實際上已經死亡;供應商沒有提供任何重大更新。 因此,我們開始從 HP UX/PA RISC 轉向 Linux/x86。 轉變始於接取伺服器的調整。

為什麼我們必須再次改變架構? 事實上,高頻交易顯著改變了系統核心的負載狀況。

假設我們有一筆小額交易導致了重大的價格變化 - 有人購買了 XNUMX 億美元。 幾毫秒後,所有市場參與者都會注意到這一點並開始做出修正。 當然,請求會排成一個巨大的隊列,系統需要很長時間才能清除。

莫斯科交易所交易和清算系統架構的演變。 第1部分

在這 50 毫秒的間隔下,平均速度約為每秒 16 個交易。 如果我們將視窗減少到 20 毫秒,那麼平均速度為每秒 90 萬筆交易,峰值時為 200 萬筆交易。 換句話說,負載不是恆定的,會突然爆發。 並且請求隊列必須始終快速處理。

但為什麼還要排隊呢? 因此,在我們的範例中,許多用戶注意到價格變化並相應地發送了交易。 它們來到網關,網關將它們序列化,設定一定的順序並將它們發送到網路。 路由器將封包打亂並轉送。 誰的包裹先到達,這筆交易就「贏了」。 結果,交易所客戶開始注意到,如果同一筆交易從多個網關發送,那麼快速處理的機會就會增加。 很快,交易機器人開始向 Gateway 發出請求,大量交易隨之出現。

莫斯科交易所交易和清算系統架構的演變。 第1部分

新一輪的演化

經過大量的測試和研究,我們轉向了即時作業系統核心。 為此,我們選擇了 RedHat Enterprise MRG Linux,其中 MRG 代表訊息即時網格。 即時修補程式的優點是它們優化了系統以盡可能快的執行:所有進程都排列在 FIFO 佇列中,核心可以隔離,不會彈出,所有事務都按嚴格的順序處理。

莫斯科交易所交易和清算系統架構的演變。 第1部分
紅色 - 在常規核心中使用佇列,綠色 - 在即時核心中工作。

但在常規伺服器上實現低延遲並不那麼容易:

  • SMI 模式在 x86 架構中是處理重要周邊裝置的基礎,幹擾很大。 各種硬體事件的處理以及元件和設備的管理都是由韌體在所謂的透明SMI模式下執行的,在這種模式下作業系統根本看不到韌體在做什麼。 通常,所有主要供應商都為韌體伺服器提供特殊擴展,以減少 SMI 處理量。
  • 不應該對處理器頻率進行動態控制,這會導致額外的停機時間。
  • 當刷新檔案系統日誌時,核心中會發生某些進程,導致不可預測的延遲。
  • 您需要注意諸如 CPU 親和力、中斷親和性、NUMA 之類的事情。

我必須說,為即時處理設定 Linux 硬體和核心的主題值得單獨寫一篇文章。 我們花了很多時間進行實驗和研究,才有了很好的結果。

當從 PA-RISC 伺服器遷移到 x86 時,我們實際上不需要對系統程式碼進行太多更改,我們只需對其進行調整和重新配置即可。 同時,我們修復了多個錯誤。 例如,PA RISC 是 Big endian 系統,而 x86 是 Little endian 系統這一事實的後果很快就浮出水面:例如,資料讀取不正確。 更棘手的錯誤是 PA RISC 使用 一貫一致 (順序一致)記憶體訪問,而 x86 可以重新排序讀取操作,因此在一個平台上絕對有效的程式碼在另一個平台上會被破壞。

切換到 x86 後,效能提高了近三倍,平均事務處理時間降低至 60 μs。

現在讓我們仔細看看系統架構發生了哪些關鍵變化。

熱備史詩

當切換到商品伺服器時,我們意識到它們不太可靠。 因此,在創建新的架構時,我們先驗地假設了一個或多個節點發生故障的可能性。 因此,需要一個能夠非常快速地切換到備用機的熱備系統。

此外,還有其他要求:

  • 在任何情況下,您都不應丟失已處理的交易。
  • 該系統必須對我們的基礎設施絕對透明。
  • 客戶端不應看到連線斷開。
  • 預訂不應造成明顯的延誤,因為這是交換的關鍵因素。

在創建雙機熱備系統時,我們沒有考慮雙重故障的場景(例如一個伺服器網路停止工作,主伺服器死機); 沒有考慮軟體中出現錯誤的可能性,因為這些錯誤是在測試過程中發現的; 並且沒有考慮硬體的錯誤操作。

結果,我們得出了以下方案:

莫斯科交易所交易和清算系統架構的演變。 第1部分

  • 主伺服器直接與網關伺服器互動。
  • 主伺服器上收到的所有交易都會透過單獨的通道立即複製到備份伺服器。 如果出現任何問題,仲裁者(州長)將協調切換。

    莫斯科交易所交易和清算系統架構的演變。 第1部分

  • 主伺服器處理每筆交易並等待備份伺服器的確認。 為了將延遲降至最低,我們避免等待交易在備份伺服器上完成。 由於交易在網路上傳輸所需的時間與執行時間相當,因此不會增加額外的延遲。
  • 我們只能查看主備伺服器上一個事務的處理狀態,目前事務的處理狀態未知。 由於我們仍然使用單執行緒進程,等待備份的回應會減慢整個處理流程,因此我們做出了合理的妥協:我們檢查了上一個事務的結果。

莫斯科交易所交易和清算系統架構的演變。 第1部分

該計劃的工作原理如下。

假設主伺服器停止回應,但網關繼續通訊。 備份伺服器發生逾時,它聯繫州長,州長為其分配主伺服器的角色,並且所有網關都切換到新的主伺服器。

如果主伺服器重新上線,它也會觸發內部逾時,因為在一段時間內沒有從網關對伺服器進行呼叫。 然後他也向總督求助,並將他排除在該計劃之外。 因此,交易所僅使用一台伺服器工作,直到交易期結束。 由於伺服器發生故障的機率相當低,因此該方案被認為是可以接受的;它不包含複雜的邏輯,並且易於測試。

要繼續進行下去。

來源: www.habr.com

添加評論