Salut à tutti ! Mi chjamu Sergey Kostanbaev, à u Scambiu aghju sviluppatu u core di u sistema di cummerciale.
Quandu i filmi di Hollywood mostranu a Borsa di New York, sempre pare cusì: folle di persone, tutti gridanu qualcosa, agitanu carte, u caosu cumpletu hè accadutu. Questu ùn hè mai accadutu quì nantu à a Borsa di Mosca, perchè u cummerciu hè statu realizatu elettronicamente da u principiu è hè basatu annantu à duie piattaforme principali - Spectra (mercatu di forex) è ASTS (mercatu di valuta, borsa è di soldi). È oghje vogliu parlà di l'evuluzione di l'architettura di u sistema di cummercializazioni è di clarificazione ASTS, di diverse suluzioni è scuperte. A storia serà longa, cusì aghju avutu a rompe in dui parti.
Semu unu di i pochi scambii in u mondu chì cummercia l'assi di tutte e classi è furnisce una gamma completa di servizii di scambiu. Per esempiu, l'annu passatu avemu classificatu secondu in u mondu in quantu à u voluminu di cummercializazioni di ubligatoriu, 25th postu trà tutti i scambii, 13th postu in capitalizazione trà i scambii publichi.
Per i participanti di cummerciale prufessiunali, i paràmetri cum'è u tempu di risposta, a stabilità di a distribuzione di u tempu (jitter) è l'affidabilità di tuttu u cumplessu sò critichi. Attualmente processemu decine di milioni di transazzioni per ghjornu. U processu di ogni transazzione da u kernel di u sistema dura decine di microsecondi. Di sicuru, l'operatori mobili nantu à a vigilia di l'annu novu o i mutori di ricerca stessi anu una carica di travagliu più altu ch'è u nostru, ma in quantu à a carica di travagliu, accumpagnata da e caratteristiche sopra citate, pochi ponu paragunà cun noi, mi pari. À u listessu tempu, hè impurtante per noi chì u sistema ùn rallenta micca per un secondu, travaglia assolutamente stabile, è tutti l'utilizatori sò in uguali.
Un pocu di storia
In u 1994, u sistema australianu ASTS hè stata lanciata nantu à u Moscow Interbank Currency Exchange (MICEX), è da quellu mumentu a storia russa di u cummerciu elettronicu pò esse cuntatu. In u 1998, l'architettura di scambiu hè stata mudernizata per intruduce u cummerciu in Internet. Da tandu, a rapidità di implementazione di novi suluzioni è cambiamenti architecturali in tutti i sistemi è i sottosistemi hè diventata solu.
In quelli anni, u sistema di scambiu hà travagliatu nantu à hardware hi-end - servitori HP Superdome 9000 ultra-affidabili (custruiti nantu à u
Ma dapoi u 2010 circa, hè apparsu un fenomenu chjamatu trading high-frequency (HFT), o high-frequency trading - simpliciamente, robots di borsa. In solu 2,5 anni, a carica nantu à i nostri servitori hè aumentata 140 volte.
Era impussibile di sustene una tale carica cù l'architettura antica è l'equipaggiu. Era necessariu d'adattà in qualchì modu.
U principiu
E dumande à u sistema di scambiu ponu esse divisu in dui tipi:
- Transacciones. Se vulete cumprà dollari, azzioni o qualcosa altru, mandate una transazzione à u sistema di cummerciale è riceve una risposta nantu à u successu.
- Richieste di informazioni. Se vulete sapè u prezzu attuale, vede u libru d'ordine o indici, poi mandate dumande d'infurmazioni.
Schematically, u core di u sistema pò esse divisu in trè livelli:
- U livellu di u cliente, à quale i brokers è i clienti travaglianu. Tutti interagiscenu cù i servitori d'accessu.
- I servitori di Gateway sò servitori di cache chì processanu in u locu tutte e dumande di informazioni. Vulete sapè à quale prezzu sò attualmente scambiati l'azzioni di Sberbank? A dumanda va à u servitore di accessu.
- Ma s'è vo vulete cumprà azzioni, allura a dumanda va à u servore cintrali (Trade Engine). Ci hè un tali servitore per ogni tipu di mercatu, ghjucanu un rolu vitale, hè per elli chì avemu creatu stu sistema.
U core di u sistema di cummerciale hè una basa di dati intelligente in memoria in quale tutte e transazzione sò transazzione di scambiu. A basa hè stata scritta in C, l'unicu dipendenze esterne eranu a libreria libc è ùn ci era micca assignazione di memoria dinamica. Per riduce u tempu di trasfurmazioni, u sistema principia cù un inseme staticu di arrays è cun traslocazione di dati statica: prima, tutte e dati per u ghjornu attuale sò caricate in memoria, è ùn hè micca più accessu à u discu, tuttu u travagliu hè realizatu solu in memoria. Quandu u sistema principia, tutti i dati di riferimentu sò digià ordinati, cusì a ricerca travaglia in modu assai efficace è piglia pocu tempu in runtime. Tutte e tavule sò fatte cù listi intrusivi è arburi per strutture di dati dinamichi in modu chì ùn anu micca bisognu di assignazione di memoria in runtime.
Andemu brevemente nantu à a storia di u sviluppu di u nostru sistema di cummercializazione è clearing.
A prima versione di l'architettura di u sistema di cummercializazione è di clarificazione hè stata custruita annantu à l'interazzione Unix: memoria sparta, semafori è fila sò stati utilizati, è ogni prucessu hè custituitu da un solu filu. Stu approcciu era spartutu in u principiu di l'anni 1990.
A prima versione di u sistema cuntene dui livelli di Gateway è un servitore cintrali di u sistema di cummerciale. U flussu di travagliu era cusì:
- U cliente manda una dumanda, chì ghjunghje à u Gateway. Cuntrolla a validità di u formatu (ma micca i dati stessu) è rifiuta e transacciones incorrecte.
- Se una dumanda d'infurmazione hè stata mandata, hè eseguita in u locu; se parlemu di una transazzione, allora hè ridiretta à u servitore cintrali.
- U mutore di cummerciale poi processa a transazzione, mudifica a memoria locale, è manda una risposta à a transazzione è a transazzione stessu per a replicazione cù un mutore di replicazione separata.
- U Gateway riceve a risposta da u node cintrali è a trasmette à u cliente.
- Dopu qualchì tempu, u Gateway riceve a transazzione per mezu di u mecanismu di replicazione, è sta volta l'eseguisce in u locu, cambiendu e so strutture di dati in modu chì e seguenti richieste d'infurmazioni mostranu l'ultimi dati.
In fatti, descrive un mudellu di replicazione in quale u Gateway hà riplicatu cumplettamente l'azzioni realizati in u sistema di cummerciale. Un canale di replicazione separatu hà assicuratu chì e transazzione sò state eseguite in u stessu ordine à traversu parechji nodi di accessu.
Siccomu u codice era unicu filatu, un schema classicu cù forche di prucessu hè stata utilizata per serve à parechji clienti. In ogni casu, era assai caru per fork tutta a basa di dati, cusì i prucessi di serviziu ligeri sò stati utilizati chì cullà i pacchetti da e sessioni TCP è i trasfirìu à una fila (SystemV Message Queue). Gateway è Trade Engine hà travagliatu solu cù questa fila, pigliendu e transazzione da quì per l'esekzione. Ùn era più pussibule di mandà una risposta à questu, perchè ùn era micca chjaru quale prucessu di serviziu duverebbe leghje. Allora avemu ricursu à un truccu: ogni prucessu forked hà creatu una fila di risposta per ellu stessu, è quandu una dumanda hè ghjunta in a fila entrata, una tag per a fila di risposta hè stata immediatamente aghjunta.
Copia constantemente una grande quantità di dati da a fila à a fila hà creatu prublemi, soprattuttu tipici per e dumande d'infurmazioni. Per quessa, avemu usatu un altru truccu: in più di a fila di risposta, ogni prucessu hà ancu creatu memoria cumuna (SystemV Shared Memory). I pacchetti stessi sò stati posti in questu, è solu una tag hè stata guardata in a fila, chì permette di truvà u pacchettu originale. Questu hà aiutatu à almacenà e dati in a cache di u processatore.
SystemV IPC include utilità per vede u statu di coda, memoria è oggetti semafori. Avemu attivamente utilizatu questu per capisce ciò chì passava in u sistema in un mumentu particulare, induve i pacchetti s'accumulavanu, ciò chì era bluccatu, etc.
I primi mudernizzioni
Prima di tuttu, avemu sbarazzatu di u Gateway unicu prucessu. U so svantaghju significativu era chì puderia gestisce una transazzione di replicazione o una dumanda d'informazione da un cliente. È cum'è a carica aumenta, Gateway duverà più tempu per processà e dumande è ùn serà micca capaci di processà u flussu di replicazione. Inoltre, se u cliente hà mandatu una transazzione, allora avete bisognu di verificà a so validità è rinviate più. Dunque, avemu rimpiazzatu u prucessu di Gateway unicu cù parechje cumpunenti chì ponu eseguisce in parallelu: infurmazioni multi-threaded è prucessi di transazzione chì funzionanu indipindentamente l'una di l'altru in una zona di memoria cumuna cù u lock RW. È à u stessu tempu avemu introduttu prucessi di spedizione è replicazione.
Impattu di u Trading d'Alta Frequenza
A versione sopra di l'architettura esisteva finu à u 2010. Intantu, ùn eramu più soddisfatti di u rendiment di i servitori HP Superdome. Inoltre, l'architettura PA-RISC era praticamente morta; u venditore ùn hà micca prupostu alcuna aghjurnazione significativa. In u risultatu, avemu cuminciatu à passà da HP UX/PA RISC à Linux/x86. A transizione principia cù l'adattazione di i servitori d'accessu.
Perchè avemu avutu à cambià l'architettura di novu? U fattu hè chì u cummerciu di alta frequenza hà cambiatu significativamente u prufilu di carica nantu à u core di u sistema.
Diciamu chì avemu una piccula transazzione chì hà causatu un cambiamentu di prezzu significativu - qualcunu hà compru una mità di miliardi di dollari. Dopu un paru di millisecondi, tutti i participanti di u mercatu avvisanu questu è cumincianu à fà una correzione. Naturalmente, e dumande sò in fila in una fila enormi, chì u sistema duverà assai tempu per sguassà.
À questu intervallu di 50 ms, a velocità media hè di circa 16 mila transazzione per seconda. Se riducemu a finestra à 20 ms, avemu una veloce media di 90 mila transazzione per seconda, cù 200 mila transazzione à u piccu. In altre parolle, a carica ùn hè micca custante, cù sbattimenti bruschi. È a fila di e dumande deve esse sempre trattata rapidamente.
Ma perchè ci hè una fila in tuttu? Allora, in u nostru esempiu, parechji utilizatori anu nutatu u cambiamentu di prezzu è anu mandatu transazzione in cunseguenza. Venenu à Gateway, li serializza, stabilisce un certu ordine è li manda à a reta. I router mischianu i pacchetti è li trasmettenu. Quale pacchettu hè ghjuntu prima, quella transazzione "vincì". In u risultatu, i clienti di scambiu cuminciaru à nutà chì, se a listessa transazzione hè stata mandata da parechji Gateways, e probabilità di u so prucessu rapidu anu aumentatu. Prestu, i robots di scambiu cuminciaru à bombardà Gateway cù dumande, è una avalanche di transazzione hè ghjunta.
Una nova volta di evoluzione
Dopu assai teste è ricerche, avemu cambiatu à u kernel di u sistema operatore in tempu reale. Per questu avemu sceltu RedHat Enterprise MRG Linux, induve MRG significa griglia di messageria in tempu reale. U vantaghju di i patches in tempu reale hè chì ottimisanu u sistema per l'esekzione più veloce pussibule: tutti i prucessi sò allineati in una fila FIFO, i core ponu esse isolati, senza ejections, tutte e transazzione sò processate in sequenza stretta.
Rossu - travagliendu cù una fila in un kernel regulare, verde - travagliendu in un kernel in tempu reale.
Ma ottene una latenza bassa in i servitori regulari ùn hè micca cusì faciule:
- U modu SMI, chì in l'architettura x86 hè a basa per travaglià cù periferiche impurtanti, interferiscenu assai. U processu di ogni tipu d'avvenimenti hardware è a gestione di cumpunenti è dispusitivi hè realizatu da u firmware in u modu chjamatu SMI trasparente, in quale u sistema operatore ùn vede micca ciò chì u firmware hè in tuttu. Comu regula, tutti i venditori maiò offrenu estensioni speciali per i servitori di firmware chì permettenu di riduce a quantità di processazione SMI.
- Ùn deve esse micca un cuntrollu dinamicu di a frequenza di u processatore, questu porta à un downtime supplementu.
- Quandu u logu di u sistema di fugliale hè sbulicatu, certi prucessi si verificanu in u kernel chì causanu ritardi imprevisible.
- Avete bisognu di attentu à e cose cum'è CPU Affinity, Interrupt affinity, NUMA.
Devu dì chì u tema di a stallazione di hardware Linux è kernel per u processu in tempu reale meriteghja un articulu separatu. Avemu passatu assai tempu à sperimentà è a ricerca prima di ottene un bonu risultatu.
Quandu si move da i servitori PA-RISC à x86, praticamenti ùn avemu micca bisognu di cambià assai u codice di u sistema, solu l'adattate è ricunfigurate. À u listessu tempu, avemu riparatu parechji bug. Per esempiu, i cunsiquenzi di u fattu chì PA RISC era un sistema Big endian, è x86 era un sistema Little endian, apparsu rapidamente: per esempiu, dati hè statu lettu incorrectly. U bug più complicatu era chì PA RISC usa
Dopu avè cambiatu à x86, u rendiment hà aumentatu quasi trè volte, u tempu mediu di trasfurmazioni di transazzione hè diminuitu à 60 μs.
Fighjemu avà un ochju più vicinu à quali cambiamenti chjave sò stati fatti à l'architettura di u sistema.
Epopea di riserva calda
Quandu hà cambiatu à i servitori di commodità, eramu cuscenti chì eranu menu affidabili. Per quessa, quandu creanu una nova architettura, a priori assumemu a pussibilità di fallimentu di unu o più nodi. Dunque, era necessariu un sistema di standby caldu chì puderia passà assai rapidamente à e macchine di salvezza.
Inoltre, ci era altre esigenze:
- In nisuna circustanza ùn devi perde transazzione processata.
- U sistema deve esse assolutamente trasparente à a nostra infrastruttura.
- I clienti ùn devenu micca vede e cunnessione abbandunate.
- A riservazione ùn deve micca intruduce un ritardu significativu perchè questu hè un fattore criticu per u scambiu.
Quandu creanu un sistema di standby caldu, ùn avemu micca cunsideratu tali scenarii cum'è doppiu fallimentu (per esempiu, a rete in un servitore hà cessatu di travaglià è u servitore principale si congelava); ùn hà micca cunsideratu a pussibilità di errori in u software perchè sò identificati durante a prova; è ùn hà micca cunsideratu l'operazione incorrecta di u hardware.
In u risultatu, avemu ghjuntu à u schema seguente:
- U servitore principale interagisce direttamente cù i servitori Gateway.
- Tutte e transazzione ricevute nantu à u servitore principale sò state replicate istantaneamente à u servitore di salvezza via un canale separatu. L'arbitru (Guvernatore) hà coordinatu u cambiamentu in casu di prublemi.
- U servitore principale hà trattatu ogni transazzione è aspittava a cunferma da u servitore di salvezza. Per mantene a latenza à u minimu, evitemu d'aspittà chì a transazzione finisci in u servitore di salvezza. Siccomu u tempu chì hà pigliatu per una transazzione per viaghjà à traversu a reta era paragunabile à u tempu d'esekzione, ùn hè stata aghjunta nisuna latenza supplementaria.
- Pudemu solu verificà l'estatus di trasfurmazioni di i servitori principali è di salvezza per a transazzione precedente, è u statutu di trasfurmazioni di a transazzione attuale era scunnisciutu. Siccomu avemu sempre aduprà prucessi unicu filatu, aspittendu una risposta da Backup avaria rallentatu tuttu u flussu di trasfurmazioni, cusì avemu fattu un cumprumissu raghjone: avemu verificatu u risultatu di a transazzione precedente.
U schema hà travagliatu cusì.
Diciamu chì u servitore principale ferma di risponde, ma i Gateways cuntinueghjanu à cumunicà. Un timeout si trova nantu à u servitore di salvezza, cuntattate u Guvernatore, chì l'assigna u rolu di u servitore principale, è tutti i Gateway cambianu à u novu servitore principale.
Se u servitore principale torna in linea, attiva ancu un timeout internu, perchè ùn ci sò micca stati chjamati à u servitore da u Gateway per un certu tempu. Allora si volta ancu à u guvernatore, è l'esclude da u schema. In u risultatu, u scambiu travaglia cun un servitore finu à a fine di u periodu di cummerciale. Siccomu a probabilità di un fallimentu di u servitore hè abbastanza bassu, stu schema era cunsideratu abbastanza accettabile; ùn cuntene micca una logica cumplessa è era faciule da pruvà.
Per esse continuatu.
Source: www.habr.com