L'evuluzione di l'architettura di u sistema di cummerciale è di clarificazione di a Borsa di Mosca. Parte 2

L'evuluzione di l'architettura di u sistema di cummerciale è di clarificazione di a Borsa di Mosca. Parte 2

Questa hè una continuazione di una longa storia nantu à a nostra strada spinosa per creà un sistema putente è di carica alta chì assicura l'operazione di u Scambio. A prima parte hè quì: habr.com/en/post/444300

Errore misteriosu

Dopu numerosi testi, u sistema di cummercializazione è di sbulicità aghjurnatu hè statu messu in opera, è avemu scontru un bug nantu à quale pudemu scrive una storia detective-mistica.

Pocu dopu avè lanciatu nantu à u servitore principale, una di e transazzione hè stata trattata cù un errore. Tuttavia, tuttu era bè nantu à u servitore di salvezza. Risultava chì una operazione matematica simplice di calculà l'esponente nantu à u servitore principale hà datu un risultatu negativu da l'argumentu veru! Avemu cuntinuatu a nostra ricerca, è in u registru SSE2 avemu trovu una diffarenza in un bit, chì hè rispunsevuli di rounding quandu u travagliu cù numeri in virgule flottante.

Avemu scrittu una utilità di prova simplice per calculà l'esponente cù u set di bit di arrotondamentu. Risultava chì in a versione di RedHat Linux chì avemu usatu, ci era un bug in u travagliu cù a funzione matematica quandu u bit malatu era inseritu. Avemu infurmatu questu à RedHat, dopu un pocu tempu avemu ricevutu un patch da elli è l'abbiamu rotulatu. L'errore ùn hè più accadutu, ma ùn era micca chjaru induve vene ancu questu bit? A funzione era rispunsevuli di questu fesetround da a lingua C. Avemu analizatu currettamente u nostru codice in cerca di u suppostu errore: avemu verificatu tutte e situazioni pussibuli; fighjulà tutte e funzioni chì anu usatu arrotondamentu; pruvatu à ripruduce una sessione falluta; utilizatu diversi compilatori cù diverse opzioni; L'analisi statica è dinamica sò stati utilizati.

A causa di l'errore ùn pò esse truvata.

Allora cuminciaru à verificà l'hardware: anu realizatu teste di carica di i prucessori; verificatu a RAM; Avemu ancu eseguitu teste per u scenariu assai improbabile di un errore multi-bit in una cellula. Per nunda.

À a fine, avemu stallatu nantu à una tiuria da u mondu di a fisica d'alta energia: qualchì particella d'alta energia hè vulata in u nostru centru di dati, hà perforatu u muru di u casu, hà culpitu u processatore è hà causatu u latch di trigger per appiccicà in quellu pocu. Questa teoria assurda era chjamata "neutrinu". Sè vo site luntanu da a fisica di particella: i neutrini quasi ùn interagiscenu micca cù u mondu esternu, è certamenti ùn sò micca capaci di affettà u funziunamentu di u processatore.

Siccomu ùn era micca pussibule di truvà a causa di u fallimentu, u servitore "offensive" hè statu sguassatu da l'operazione per u casu.

Dopu qualchì tempu, avemu principiatu à migliurà u sistema di salvezza calda: avemu introduttu cusì chjamati "riserve calde" (warm) - rèplichi asincroni. Anu ricivutu un flussu di transazzione chì puderia esse situatu in diversi centri di dati, ma i caldi ùn anu micca interazzione attivamente cù altri servitori.

L'evuluzione di l'architettura di u sistema di cummerciale è di clarificazione di a Borsa di Mosca. Parte 2

Perchè hè statu fattu questu? Se u servitore di salvezza falla, allora caldu ligatu à u servitore principale diventa a nova copia di salvezza. Questu hè, dopu à un fallimentu, u sistema ùn ferma micca cù un servitore principale finu à a fine di a sessione di cummerciale.

È quandu a nova versione di u sistema hè stata pruvata è messa in funziunamentu, l'errore di arrotondamentu hè accadutu di novu. Inoltre, cù l'aumentu di u numeru di servitori caldi, l'errore cuminciò à cumparisce più spessu. À u listessu tempu, u vinditore ùn avia nunda à mustrà, postu chì ùn ci era micca evidenza concreta.

Duranti u prossimu analisi di a situazione, una tiurìa hè ghjunta chì u prublema puderia esse ligata à u SO. Avemu scrittu un prugramma simplice chì chjama una funzione in un ciclu infinitu fesetround, s'arricorda u statu attuale è u cuntrolla à traversu u sonnu, è questu hè fattu in parechji fili cuncurrenti. Dopu avè sceltu i paràmetri per u sonnu è u nùmeru di fili, avemu cuminciatu à ripruduce in modu coherente u fallimentu di bit dopu à circa 5 minuti di esecuzione di l'utilità. Tuttavia, u supportu di Red Hat ùn era micca capaci di ripruduce. A prova di i nostri altri servitori hà dimustratu chì solu quelli cù certi processori sò suscettibili à l'errore. À u listessu tempu, cambià à un novu kernel risolve u prublema. À a fine, avemu solu rimpiazzatu u SO, è a vera causa di u bug ùn era micca chjaru.

È di colpu l'annu passatu un articulu hè statu publicatu annantu à Habré "Cumu aghju trovu un bug in i processori Intel Skylake" A situazione descritta in questu era assai simili à a nostra, ma l'autore hà purtatu l'investigazione più in là è hà presentatu una teoria chì l'errore era in u microcode. È quandu i kernels Linux sò aghjurnati, i pruduttori aghjurnanu ancu u microcode.

Ulteriore sviluppu di u sistema

Ancu s'è avemu sbarazzatu di l'errore, sta storia ci hà obligatu à ricunsiderà l'architettura di u sistema. Dopu tuttu, ùn eramu micca prutetti da a ripetizione di tali bugs.

I principii seguenti formanu a basa per i prossimi migliuramentu di u sistema di riservazione:

  • Ùn pudete micca fiducia in nimu. I servitori ùn ponu micca funziona bè.
  • Riserva di a maiò parte.
  • Assicurendu cunsensu. Cum'è un aghjuntu logicu à a riservazione di a maiurità.
  • Doppiu fallimentu hè pussibule.
  • Vitalità. U novu schema di standby caldu ùn deve esse micca peggiu di u precedente. U cummerciu duveria prucede senza interruzzione finu à l'ultimu servitore.
  • Ligeru aumentu di a latenza. Ogni downtime implica enormi perdite finanziarie.
  • Interazione minima di a rete per mantene a latenza u più bassu pussibule.
  • Selezzione di un novu servitore maestru in seconde.

Nisuna di e suluzioni dispunibili nantu à u mercatu ùn ci hè adattatu, è u protokollu Raft era sempre in a so infanzia, cusì avemu creatu a nostra propria suluzione.

L'evuluzione di l'architettura di u sistema di cummerciale è di clarificazione di a Borsa di Mosca. Parte 2

Networking

In più di u sistema di riservazione, avemu cuminciatu à mudernizà l'interazzione di a rete. U subsistema I / O hè custituitu da parechji prucessi, chì anu avutu u peghju impattu nantu à u jitter è a latenza. Cù centinaie di prucessi chì manipulanu e cunnessione TCP, avemu statu custrettu à cambià constantemente trà elli, è in una scala di microsecondi hè una operazione piuttostu longa. Ma u peghju hè chì quandu un prucessu hà ricivutu un pacchettu per u processu, l'hà mandatu à una fila di SystemV è dopu aspittava un avvenimentu da una altra fila di SystemV. In ogni casu, quandu ci hè un gran numaru di nodi, l'arrivu di un novu pacchettu TCP in un prucessu è a ricezione di dati in a fila in un altru rapprisentanu dui avvenimenti cuncurrenti per u SO. In questu casu, s'ellu ùn ci hè micca un processore fisicu dispunibule per i dui compiti, unu serà processatu, è u sicondu serà piazzatu in una fila d'attesa. Hè impussibile di predichendu e cunsequenze.

In tali situazioni, u cuntrollu di priorità di u prucessu dinamicu pò esse usatu, ma questu serà bisognu di l'usu di chjamati di sistema intensivi di risorse. In u risultatu, avemu cambiatu à un filu cù l'epoll classicu, questu hà aumentatu assai a velocità è hà riduciutu u tempu di trasfurmazioni di transazzione. Avemu ancu sbarazzatu di i prucessi di cumunicazione di a rete separata è di a cumunicazione per SystemV, hà riduciutu significativamente u nùmeru di chjamate di u sistema è hà cuminciatu à cuntrullà e priorità di l'operazioni. In u subsistema I / O solu, era pussibule di salvà circa 8-17 microsecondi, secondu u scenariu. Stu schema unicu filatu hè statu utilizatu senza cambià da tandu; un filu epoll cun un margine hè abbastanza per serve tutte e cunnessione.

Trattamentu di transazzione

A carica crescente in u nostru sistema hà bisognu di l'aghjurnamentu di quasi tutti i so cumpunenti. Ma, sfurtunatamenti, a stagnazione in a crescita di a velocità di u clock di u processore in l'ultimi anni ùn hà più permessu di scala i prucessi in testa. Per quessa, avemu decisu di dividisce u prucessu di u Engine in trè livelli, cù u più occupatu di elli hè u sistema di cuntrollu di risicu, chì evalua a dispunibilità di fondi in i cunti è crea e transazzioni stessi. Ma i soldi ponu esse in diverse valute, è era necessariu di calculà nantu à quale basa u trattamentu di e dumande deve esse divisu.

A suluzione logica hè di dividisce per munita: un servitore cummercia in dollari, un altru in lire, è un terzu in euro. Ma se, cù un tali schema, duie transazzione sò mandati per cumprà diverse valute, allora u prublema di a desincronizazione di a billetera si presenta. Ma a sincronizazione hè difficiule è caru. Per quessa, saria currettu di shard separatamente da wallets è separatamente da strumenti. Per via, a maiò parte di i scambii occidentali ùn anu micca u compitu di cuntrollà i risichi in modu acutu cum'è noi, cusì a maiò spessu questu hè fattu offline. Avemu bisognu di implementà a verificazione in linea.

Spieghemu cun un esempiu. Un trader vole cumprà $ 30, è a dumanda và à a validazione di a transazzione: cuntrollemu se stu trader hè permessu di stu modu di cummerciale è s'ellu hà i diritti necessarii. Se tuttu hè in ordine, a dumanda va à u sistema di verificazione di risichi, i.e. per verificà a sufficienza di fondi per cuncludi una transazzione. Ci hè una nota chì a quantità necessaria hè attualmente bluccata. A dumanda hè poi trasmessa à u sistema di cummerciale, chì appruva o disapprova a transazzione. Dicemu chì a transazzione hè appruvata - allora u sistema di verificazione di risichi marca chì i soldi sò sbloccati, è i rubli si trasformanu in dollari.

In generale, u sistema di cuntrollu di risichi cuntene algoritmi cumplessi è eseguisce una grande quantità di calculi assai intensivi di risorse, è ùn hè micca solu cuntrollà u "equilibriu di u contu", cum'è puderia pare à prima vista.

Quandu avemu cuminciatu à dividisce u prucessu di u Motore in livelli, avemu scontru un prublema: u codice chì era dispunibule in quellu tempu hà utilizatu attivamente a listessa matrice di dati in i fasi di validazione è verificazione, chì necessitava di riscrittura di tutta a basa di codice. In u risultatu, avemu pigliatu prestu una tecnica per processà l'istruzzioni da i prucessori muderni: ognuna di elle hè divisa in picculi tappe è parechje azzioni sò realizati in parallelu in un ciculu.

L'evuluzione di l'architettura di u sistema di cummerciale è di clarificazione di a Borsa di Mosca. Parte 2

Dopu una piccula adattazione di u codice, avemu creatu un pipeline per u processu di transazzione parallela, in quale a transazzione hè stata divisa in 4 tappe di u pipeline: interazzione di rete, validazione, esecuzione è publicazione di u risultatu.

L'evuluzione di l'architettura di u sistema di cummerciale è di clarificazione di a Borsa di Mosca. Parte 2

Fighjemu un esempiu. Avemu dui sistemi di trasfurmazioni, seriali è paralleli. A prima transazzione arriva è hè mandata per a validazione in i dui sistemi. A seconda transazzione ghjunghje subitu: in un sistema parallelu hè immediatamente pigliatu à u travagliu, è in un sistema sequenziale si mette in una fila aspittendu chì a prima transazzione passa per u stadiu di prucessu attuale. Questu hè, u vantaghju principale di u processu di pipeline hè chì processemu a fila di transazzione più veloce.

Hè cusì chì avemu ghjuntu cù u sistema ASTS +.

True, micca tuttu hè cusì lisu cù trasportatori. Diciamu chì avemu una transazzione chì affetta l'array di dati in una transazzione vicina; questa hè una situazione tipica per un scambiu. Una tale transazzione ùn pò esse eseguita in un pipeline perchè pò influenzà l'altri. Sta situazione hè chjamata periculu di dati, è tali transazzione sò simpliciamente trattate per separatamente: quandu e transazzione "veloce" in a fila scorri, u pipeline si ferma, u sistema processa a transazzione "lenta", è poi principia u pipeline di novu. Fortunatamente, a proporzione di tali transazzione in u flussu generale hè assai chjuca, cusì u pipeline ferma cusì raramente chì ùn hà micca affettatu u rendiment generale.

L'evuluzione di l'architettura di u sistema di cummerciale è di clarificazione di a Borsa di Mosca. Parte 2

Allora avemu cuminciatu à risolve u prublema di sincronizà trè fili di esicuzzioni. U risultatu era un sistema basatu annantu à un buffer anellu cù cellule di dimensione fissa. In questu sistema, tuttu hè sottumessu à a velocità di trasfurmazioni; i dati ùn sò micca copiati.

  • Tutti i pacchetti di rete entranti entranu in a tappa di allocazione.
  • Li mettemu in un array è li marcamu cum'è dispunibuli per a tappa #1.
  • A seconda transazzione hè ghjunta, hè torna dispunibule per u stadiu n ° 1.
  • U primu filu di trasfurmazioni vede e transazzione dispunibuli, li processa, è li move à u prossimu stadiu di u sicondu filu di trasfurmazioni.
  • Allora prucessa a prima transazzione è marca a cellula currispundente deleted - hè avà dispunibule per u novu usu.

Tutta a fila hè trattata in questu modu.

L'evuluzione di l'architettura di u sistema di cummerciale è di clarificazione di a Borsa di Mosca. Parte 2

U processu di ogni stadiu piglia unità o decine di microsecondi. E s'è avemu usatu schemi di sincronizazione OS standard, allora perdemu più tempu nantu à a sincronizazione stessu. Hè per quessa chì avemu cuminciatu à aduprà spinlock. In ogni casu, questu hè una forma assai pessima in un sistema in tempu reale, è RedHat ùn ricumandemu micca di fà questu, cusì applichemu un spinlock per 100 ms, è poi passà à u modu di semaforu per eliminà a pussibilità di un bloccu.

In u risultatu, avemu ottinutu un rendimentu di circa 8 milioni di transazzione per seconda. È literalmente dui mesi dopu articulu circa LMAX Disruptor avemu vistu una descrizzione di un circuitu cù a listessa funziunalità.

L'evuluzione di l'architettura di u sistema di cummerciale è di clarificazione di a Borsa di Mosca. Parte 2

Avà puderia esse parechje fili di esicuzzioni in una tappa. Tutte e transazzione sò state trattate una per una, in l'ordine ch'elli anu ricevutu. In u risultatu, u rendiment di punta hè aumentatu da 18 mila à 50 mila transazzione per seconda.

Sistema di gestione di risicu di scambiu

Ùn ci hè micca un limite à a perfezione, è prestu avemu principiatu a mudernizazione di novu: in u quadru di ASTS +, avemu cuminciatu à trasfurmà i sistemi di gestione di risichi è operazioni di liquidazione in cumpunenti autonomi. Avemu sviluppatu una architettura muderna flexible è un novu mudellu di risicu gerarchicu, è pruvatu à utilizà a classa induve pussibule fixed_point invece di double.

Ma un prublema subitu subitu: cumu sincronizà tutta a logica di l'affari chì hà travagliatu da parechji anni è trasfirìu à u novu sistema? In u risultatu, a prima versione di u prototipu di u novu sistema hà da esse abbandunatu. A seconda versione, chì travaglia attualmente in a produzzione, hè basatu annantu à u listessu codice, chì travaglia in e parti di cummerciale è di risicu. Durante u sviluppu, a cosa più duru di fà era git merge trà duie versioni. U nostru cumpagnu Evgeniy Mazurenok hà realizatu sta operazione ogni settimana è ogni volta hà maleditu per un tempu assai longu.

Quandu selezziunate un novu sistema, avemu avutu subitu à risolve u prublema di interazzione. Quandu sceglite un bus di dati, era necessariu di assicurà un jitter stabile è una latenza minima. A reta di InfiniBand RDMA era più adattata per questu: u tempu mediu di trasfurmazioni hè 4 volte più menu cà in e rete Ethernet 10 G. Ma ciò chì ci hà veramente captivatu hè a diffarenza in percentile - 99 è 99,9.

Di sicuru, InfiniBand hà i so sfide. Prima, una API differente - ibverbs invece di sockets. Siconda, ùn ci sò quasi micca suluzioni di messageria open source largamente disponibile. Avemu pruvatu à fà u nostru propiu prototipu, ma hè diventatu assai difficiule, cusì avemu sceltu una suluzione cummerciale - Confinity Low Latency Messaging (ex IBM MQ LLM).

Allora u compitu di dividisce bè u sistema di risicu hè ghjuntu. Se simpricimenti sguassate u Risk Engine è ùn creanu micca un node intermediu, e transacciones da dui fonti ponu esse mischiati.

L'evuluzione di l'architettura di u sistema di cummerciale è di clarificazione di a Borsa di Mosca. Parte 2

E soluzioni chjamate Ultra Low Latency anu un modu di reordine: e transazzioni da duie fonti ponu esse disposti in l'ordine necessariu dopu a ricezione; questu hè implementatu cù un canale separatu per scambià infurmazioni nantu à l'ordine. Ma ùn avemu micca ancu aduprà stu modu: complicate tuttu u prucessu, è in una quantità di suluzioni ùn hè micca supportatu in tuttu. In più, ogni transazzione avissi da esse assignati timestamps currispundenti, è in u nostru schema stu mecanismu hè assai difficiuli di implementà currettamente. Dunque, avemu usatu u schema classicu cù un broker di messagiu, vale à dì cù un dispatcher chì distribuisce missaghji trà u Risk Engine.

U sicondu prublema hè stata ligata à l'accessu di u cliente: se ci sò parechji Risk Gateways, u cliente hà bisognu di cunnette cù ognuna di elli, è questu serà bisognu di cambiamenti à a capa di u cliente. Vulemu alluntanassi da questu in questa tappa, cusì u cuncepimentu attuale di Risk Gateway processa tuttu u flussu di dati. Questu limita assai u throughput massimu, ma simplifica assai l'integrazione di u sistema.

Duplicazione

U nostru sistema ùn deve micca avè un unicu puntu di fallimentu, vale à dì, tutti i cumpunenti deve esse duplicati, cumpresu u broker di messagiu. Avemu risoltu stu prublema cù u sistema CLLM: cuntene un cluster RCMS in quale dui dispatchers ponu travaglià in modu maestru-slave, è quandu unu falla, u sistema cambia automaticamente à l'altru.

U travagliu cù un centru di dati di salvezza

InfiniBand hè ottimizatu per u funziunamentu cum'è una reta lucale, vale à dì, per cunnette l'equipaggiu di rack-mount, è una reta InfiniBand ùn pò esse stallata trà dui centri di dati distribuiti geograficamente. Per quessa, avemu implementatu un ponte / dispatcher, chì cunnetta à l'almacenamiento di messagi via e rete Ethernet regulare è trasmette tutte e transazzione à una seconda rete IB. Quandu avemu bisognu di migrà da un centru di dati, pudemu sceglie quale centru di dati per travaglià avà.

Risultati

Tuttu ciò chì sopra ùn hè statu fattu in una volta; ci hà pigliatu parechje iterazioni di sviluppà una nova architettura. Avemu creatu u prototipu in un mesi, ma hà pigliatu più di dui anni per mette in cundizione di travagliu. Avemu pruvatu à ottene u megliu cumprumissu trà l'aumentu di u tempu di trasfurmazioni di transazzione è l'aumentu di l'affidabilità di u sistema.

Siccomu u sistema hè statu assai aghjurnatu, avemu implementatu a ricuperazione di dati da duie fonti indipendenti. Se u magazzinu di missaghju ùn funziona micca bè per una certa ragione, pudete piglià u logu di transazzione da una seconda fonte - da u Risk Engine. Stu principiu hè osservatu in tuttu u sistema.

Frà altre cose, pudemu priservà l'API di u cliente in modu chì nè i brokers nè nimu ùn anu bisognu di una ripresa significativa per a nova architettura. Avemu avutu à cambià qualchi interfacce, ma ùn ci era micca bisognu di fà cambiamenti significativu à u mudellu di uperazione.

Avemu chjamatu a versione attuale di a nostra piattaforma Rebus - cum'è abbreviazione per e duie innovazioni più notevuli in l'architettura, Risk Engine è BUS.

L'evuluzione di l'architettura di u sistema di cummerciale è di clarificazione di a Borsa di Mosca. Parte 2

In principiu, vulemu assignà solu a parte di pulizziari, ma u risultatu era un sistema distribuitu enormi. I Clienti ponu avà interagisce cù u Trade Gateway, u Clearing Gateway, o i dui.

Ciò chì avemu ultimamente ottenutu:

L'evuluzione di l'architettura di u sistema di cummerciale è di clarificazione di a Borsa di Mosca. Parte 2

Riduce u livellu di latenza. Cù un picculu voluminu di transazzione, u sistema funziona u listessu cum'è a versione precedente, ma à u stessu tempu pò sustene una carica assai più altu.

U rendiment di punta hè aumentatu da 50 mila à 180 mila transazzione per seconda. Un aumentu ulteriore hè impeditu da l'unicu flussu di currispundenza d'ordine.

Ci hè duie manere per più migliuramentu: parallelizà l'abbinamentu è cambià a manera di travaglià cù Gateway. Avà tutti i Gateways operanu secondu un schema di replicazione, chì, sottu una tale carica, cessà di funziunà nurmale.

Infine, possu dà un pocu di cunsiglii à quelli chì finalizanu i sistemi di l'impresa:

  • Siate preparatu per u peghju in ogni mumentu. I prublemi sò sempre inaspettati.
  • Di solitu hè impussibile di rinfurzà rapidamente l'architettura. Soprattuttu s'ellu ci vole à ottene a massima affidabilità in parechje indicatori. Più nodi, più risorse necessarie per u sustegnu.
  • Tutte e soluzioni persunalizate è proprietarie necessitanu risorse supplementari per a ricerca, supportu è mantenimentu.
  • Ùn lasciate micca risolve i prublemi di affidabilità di u sistema è di ricuperazione dopu i fallimenti; pigliateli in contu in a fase iniziale di cuncepimentu.

Source: www.habr.com

Add a comment