Evolucija arhitekture sistema trgovanja i kliringa Moskovske berze. Dio 2

Evolucija arhitekture sistema trgovanja i kliringa Moskovske berze. Dio 2

Ovo je nastavak duge priče o našem trnovitom putu ka stvaranju moćnog sistema visokog opterećenja koji osigurava rad Berze. Prvi dio je ovdje: habr.com/en/post/444300

Misteriozna greška

Nakon brojnih testiranja, ažurirani sistem trgovanja i kliringa je pušten u rad, te smo naišli na grešku o kojoj bismo mogli napisati detektivsko-mističnu priču.

Ubrzo nakon pokretanja na glavnom serveru, jedna od transakcija je obrađena s greškom. Međutim, na backup serveru je sve bilo u redu. Ispostavilo se da je jednostavna matematička operacija izračunavanja eksponenta na glavnom serveru dala negativan rezultat iz stvarnog argumenta! Nastavili smo istraživanje i u registru SSE2 pronašli smo razliku u jednom bitu, koji je odgovoran za zaokruživanje pri radu sa brojevima s pomičnim zarezom.

Napisali smo jednostavan test uslužni program za izračunavanje eksponenta sa postavljenim bitom zaokruživanja. Ispostavilo se da je u verziji RedHat Linuxa koju smo koristili došlo do greške u radu sa matematičkom funkcijom kada je ubačen nesrećni bit. To smo prijavili RedHatu, nakon nekog vremena dobili smo zakrpu od njih i izbacili je. Greška se više nije javljala, ali nije bilo jasno odakle je uopće došao ovaj bit? Funkcija je bila odgovorna za to fesetround iz jezika C. Pažljivo smo analizirali naš kod u potrazi za navodnom greškom: provjerili smo sve moguće situacije; pogledao sve funkcije koje koriste zaokruživanje; pokušao da reprodukuje neuspelu sesiju; koristili različite kompajlere sa različitim opcijama; Korištene su statičke i dinamičke analize.

Uzrok greške nije pronađen.

Zatim su počeli provjeravati hardver: izvršili su testiranje opterećenja procesora; provjerio RAM; Čak smo izvršili testove za vrlo malo vjerojatan scenario višebitne greške u jednoj ćeliji. Uzalud.

Na kraju smo se odlučili na teoriju iz svijeta fizike visokih energija: neka visokoenergetska čestica je uletjela u naš podatkovni centar, probila zid kućišta, udarila u procesor i uzrokovala da se brava okidača zaglavi baš u tom dijelu. Ova apsurdna teorija nazvana je "neutrino". Ako ste daleko od fizike čestica: neutrini gotovo da nemaju interakciju s vanjskim svijetom, a sigurno nisu u stanju utjecati na rad procesora.

S obzirom da nije bilo moguće pronaći uzrok kvara, „uvredljivi“ server je za svaki slučaj uklonjen iz rada.

Nakon nekog vremena počeli smo da poboljšavamo sistem vruće sigurnosne kopije: uveli smo takozvane “tople rezerve” (tople) - asinhrone replike. Primili su niz transakcija koje su se mogle nalaziti u različitim podatkovnim centrima, ali topline nisu aktivno komunicirale s drugim serverima.

Evolucija arhitekture sistema trgovanja i kliringa Moskovske berze. Dio 2

Zašto je to urađeno? Ako rezervni server pokvari, tada toplo vezan za glavni server postaje nova rezervna kopija. Odnosno, nakon kvara, sistem ne ostaje sa jednim glavnim serverom do kraja trgovačke sesije.

A kada je nova verzija sistema testirana i puštena u rad, ponovo se pojavila greška bita zaokruživanja. Štaviše, s povećanjem broja toplih servera, greška se počela pojavljivati ​​sve češće. Istovremeno, prodavac nije imao šta da pokaže, jer nije bilo konkretnih dokaza.

Prilikom sljedeće analize situacije pojavila se teorija da bi problem mogao biti vezan za OS. Napisali smo jednostavan program koji poziva funkciju u beskonačnoj petlji fesetround, pamti trenutno stanje i provjerava ga kroz spavanje, a to se radi u mnogim konkurentskim nitima. Nakon što smo odabrali parametre za spavanje i broj niti, počeli smo dosljedno reproducirati kvar bita nakon otprilike 5 minuta pokretanja uslužnog programa. Međutim, Red Hat podrška nije mogla to reproducirati. Testiranje ostalih naših servera pokazalo je da su samo oni sa određenim procesorima podložni grešci. U isto vrijeme, prelazak na novi kernel riješio je problem. Na kraju smo jednostavno zamijenili OS, a pravi uzrok greške je ostao nejasan.

I odjednom je prošle godine objavljen članak na Habréu “Kako sam pronašao grešku u Intel Skylake procesorima" Situacija koja je u njoj opisana bila je vrlo slična našoj, ali je autor nastavio istraživanje i iznio teoriju da je greška u mikrokodu. A kada se Linux kerneli ažuriraju, proizvođači također ažuriraju mikrokod.

Dalji razvoj sistema

Iako smo se riješili greške, ova priča nas je natjerala da preispitamo arhitekturu sistema. Uostalom, nismo bili zaštićeni od ponavljanja takvih grešaka.

Sljedeći principi formirali su osnovu za naredna poboljšanja sistema rezervacija:

  • Ne možeš nikome vjerovati. Serveri možda neće raditi ispravno.
  • Vecinska rezervacija.
  • Osiguravanje konsenzusa. Kao logičan dodatak većinskoj rezervi.
  • Mogući su dvostruki kvarovi.
  • Vitalnost. Nova shema vruće pripravnosti ne bi trebala biti gora od prethodne. Trgovanje treba da se odvija bez prekida do poslednjeg servera.
  • Blago povećanje latencije. Svaki zastoj povlači velike finansijske gubitke.
  • Minimalna mrežna interakcija kako bi latencija bila što manja.
  • Odabir novog glavnog servera za sekunde.

Nijedno od rješenja dostupnih na tržištu nam nije odgovaralo, a Raft protokol je još bio u povojima pa smo kreirali vlastito rješenje.

Evolucija arhitekture sistema trgovanja i kliringa Moskovske berze. Dio 2

Umrežavanje

Pored sistema rezervacija, započeli smo modernizaciju mrežne interakcije. I/O podsistem se sastojao od mnogih procesa, koji su imali najgori uticaj na podrhtavanje i kašnjenje. Sa stotinama procesa koji rukuju TCP konekcijama, bili smo primorani da se stalno prebacujemo između njih, a na mikrosekundnoj skali ovo je prilično dugotrajna operacija. Ali najgore je to što kada je proces primio paket na obradu, poslao ga je u jedan SystemV red, a zatim čekao događaj iz drugog SystemV reda. Međutim, kada postoji veliki broj čvorova, dolazak novog TCP paketa u jednom procesu i prijem podataka u red u drugom predstavljaju dva konkurentska događaja za OS. U ovom slučaju, ako nema fizičkih procesora dostupnih za oba zadatka, jedan će biti obrađen, a drugi će biti stavljen u red čekanja. Nemoguće je predvidjeti posljedice.

U takvim situacijama može se koristiti dinamička kontrola prioriteta procesa, ali to će zahtijevati korištenje sistemskih poziva koji zahtijevaju velike resurse. Kao rezultat toga, prešli smo na jednu nit koristeći klasični epoll, što je uvelike povećalo brzinu i smanjilo vrijeme obrade transakcije. Također smo se riješili odvojenih mrežnih komunikacijskih procesa i komunikacije preko SystemV-a, značajno smanjili broj sistemskih poziva i počeli kontrolirati prioritete rada. Samo na I/O podsistemu bilo je moguće uštedjeti oko 8-17 mikrosekundi, ovisno o scenariju. Ova jednonitna šema se od tada koristi nepromijenjena; jedna epoll nit sa marginom dovoljna je za servisiranje svih veza.

Obrada transakcija

Sve veće opterećenje našeg sistema zahtijevalo je nadogradnju gotovo svih njegovih komponenti. Ali, nažalost, stagnacija u rastu brzine procesora u posljednjih nekoliko godina više nije omogućila direktno skaliranje procesa. Stoga smo odlučili da proces Engine podijelimo na tri nivoa, od kojih je najopterećeniji sistem za provjeru rizika, koji procjenjuje dostupnost sredstava na računima i kreira same transakcije. Ali novac može biti u različitim valutama i trebalo je shvatiti po kom osnovu treba podijeliti obradu zahtjeva.

Logično rešenje je da se podeli po valuti: jedan server trguje u dolarima, drugi u funtama, a treći u evrima. Ali ako se s takvom shemom pošalju dvije transakcije za kupovinu različitih valuta, tada će se pojaviti problem desinhronizacije novčanika. Ali sinhronizacija je teška i skupa. Stoga bi bilo ispravno podijeliti odvojeno po novčanicima i odvojeno po instrumentima. Inače, većina zapadnih berzi nema zadatak da provjerava rizike tako akutno kao mi, pa se to najčešće radi van mreže. Trebali smo implementirati online verifikaciju.

Objasnimo na primjeru. Trgovac želi kupiti 30 dolara, a zahtjev ide na validaciju transakcije: provjeravamo da li je ovom trgovcu dozvoljen ovaj način trgovanja i da li ima potrebna prava. Ako je sve u redu, zahtjev ide u sistem za provjeru rizika, tj. provjeriti dovoljnost sredstava za zaključenje transakcije. Postoji napomena da je traženi iznos trenutno blokiran. Zahtjev se zatim prosljeđuje trgovačkom sistemu, koji odobrava ili ne odobrava transakciju. Recimo da je transakcija odobrena - tada sistem za provjeru rizika označava da je novac deblokiran, a rublje se pretvaraju u dolare.

Općenito, sistem za provjeru rizika sadrži složene algoritme i obavlja veliku količinu proračuna koji zahtijevaju velike resurse, a ne samo provjeravaju „stanje računa“, kako se na prvi pogled može činiti.

Kada smo počeli da delimo Engine proces na nivoe, naišli smo na problem: kod koji je bio dostupan u to vreme aktivno je koristio isti niz podataka u fazama validacije i verifikacije, što je zahtevalo prepisivanje cele baze koda. Kao rezultat toga, posudili smo tehniku ​​za obradu instrukcija od modernih procesora: svaki od njih je podijeljen u male faze i nekoliko radnji se izvodi paralelno u jednom ciklusu.

Evolucija arhitekture sistema trgovanja i kliringa Moskovske berze. Dio 2

Nakon male adaptacije koda, kreirali smo cjevovod za paralelnu obradu transakcija, u kojem je transakcija podijeljena u 4 faze cjevovoda: mrežna interakcija, validacija, izvršenje i objavljivanje rezultata

Evolucija arhitekture sistema trgovanja i kliringa Moskovske berze. Dio 2

Pogledajmo primjer. Imamo dva sistema obrade, serijski i paralelni. Prva transakcija stiže i šalje se na validaciju u oba sistema. Druga transakcija odmah stiže: u paralelnom sistemu se odmah pokreće, au sekvencijalnom sistemu se stavlja u red čekanja da prva transakcija prođe kroz trenutnu fazu obrade. Odnosno, glavna prednost procesiranja cevovoda je što brže obrađujemo red transakcija.

Ovako smo došli do ASTS+ sistema.

Istina, ni sa transporterima nije sve tako glatko. Recimo da imamo transakciju koja utiče na nizove podataka u susednoj transakciji; ovo je tipična situacija za razmenu. Takva transakcija se ne može izvršiti u cjevovodu jer može utjecati na druge. Ova situacija se naziva opasnost od podataka, i takve transakcije se jednostavno obrađuju odvojeno: kada se "brze" transakcije u redu čekaju, cevovod se zaustavlja, sistem obrađuje "sporu" transakciju, a zatim ponovo pokreće cevovod. Srećom, udio takvih transakcija u ukupnom toku je vrlo mali, tako da se cevovod zaustavlja tako rijetko da ne utiče na ukupne performanse.

Evolucija arhitekture sistema trgovanja i kliringa Moskovske berze. Dio 2

Tada smo počeli rješavati problem sinhronizacije tri niti izvršavanja. Rezultat je bio sistem baziran na prstenastom baferu sa ćelijama fiksne veličine. U ovom sistemu sve je podložno brzini obrade, podaci se ne kopiraju.

  • Svi dolazni mrežni paketi ulaze u fazu dodjele.
  • Postavljamo ih u niz i označavamo ih kao dostupne za fazu #1.
  • Druga transakcija je stigla, ponovo je dostupna za fazu br. 1.
  • Prva nit obrade vidi dostupne transakcije, obrađuje ih i premješta ih u sljedeću fazu druge niti obrade.
  • Zatim obrađuje prvu transakciju i označava odgovarajuću ćeliju deleted — sada je dostupan za novu upotrebu.

Na ovaj način se obrađuje cijeli red čekanja.

Evolucija arhitekture sistema trgovanja i kliringa Moskovske berze. Dio 2

Obrada svake faze traje jedinicama ili desetinama mikrosekundi. A ako koristimo standardne sheme sinhronizacije OS-a, izgubit ćemo više vremena na samoj sinhronizaciji. Zato smo počeli koristiti spinlock. Međutim, ovo je vrlo loša forma u sistemu u realnom vremenu, i RedHat to striktno ne preporučuje, pa primjenjujemo spinlock na 100 ms, a zatim prelazimo u način rada semafora kako bismo eliminirali mogućnost zastoja.

Kao rezultat toga, postigli smo učinak od oko 8 miliona transakcija u sekundi. I bukvalno dva meseca kasnije članak o LMAX Disruptoru vidjeli smo opis kola sa istom funkcionalnošću.

Evolucija arhitekture sistema trgovanja i kliringa Moskovske berze. Dio 2

Sada može postojati nekoliko niti izvršenja u jednoj fazi. Sve transakcije su obrađene jedna po jedna, redoslijedom kojim su primljene. Kao rezultat toga, vršne performanse su porasle sa 18 hiljada na 50 hiljada transakcija u sekundi.

Sistem upravljanja rizikom berze

Ne postoji granica savršenstvu i ubrzo smo ponovo počeli sa modernizacijom: u okviru ASTS+, počeli smo da prebacujemo sisteme upravljanja rizicima i operacija poravnanja u autonomne komponente. Razvili smo fleksibilnu modernu arhitekturu i novi hijerarhijski model rizika, te pokušali koristiti klasu gdje god je to moguće fixed_point umjesto double.

Ali odmah je nastao problem: kako uskladiti svu poslovnu logiku koja radi dugi niz godina i prenijeti je na novi sistem? Kao rezultat toga, prva verzija prototipa novog sistema morala je biti napuštena. Druga verzija, koja je trenutno u produkciji, bazirana je na istom kodu, koji radi i u dijelu trgovanja i u dijelu rizika. Tokom razvoja, najteže je bilo git merge između dvije verzije. Naš kolega Evgeniy Mazurenok obavljao je ovu operaciju svake sedmice i svaki put je psovao jako dugo.

Prilikom odabira novog sistema, odmah smo morali riješiti problem interakcije. Prilikom odabira sabirnice podataka, bilo je potrebno osigurati stabilan jitter i minimalno kašnjenje. InfiniBand RDMA mreža je bila najprikladnija za ovo: prosječno vrijeme obrade je 4 puta manje nego u 10 G Ethernet mrežama. Ali ono što nas je zaista oduševilo je razlika u percentilima - 99 i 99,9.

Naravno, InfiniBand ima svoje izazove. Prvo, drugačiji API - ibverbs umjesto utičnica. Drugo, gotovo da ne postoje široko dostupna rješenja za razmjenu poruka otvorenog koda. Pokušali smo napraviti vlastiti prototip, ali se pokazalo da je to vrlo teško, pa smo odabrali komercijalno rješenje - Confinity Low Latency Messaging (ranije IBM MQ LLM).

Tada se pojavio zadatak pravilne podjele sistema rizika. Ako jednostavno uklonite Risk Engine i ne kreirate međučvor, onda se transakcije iz dva izvora mogu miješati.

Evolucija arhitekture sistema trgovanja i kliringa Moskovske berze. Dio 2

Takozvana Ultra Low Latency rješenja imaju način ponovnog naručivanja: transakcije iz dva izvora mogu se rasporediti po traženom redoslijedu po prijemu, što se implementira pomoću posebnog kanala za razmjenu informacija o nalogu. Ali mi još ne koristimo ovaj način rada: komplicira cijeli proces, a u brojnim rješenjima uopće nije podržan. Osim toga, svakoj transakciji bi se morale dodijeliti odgovarajuće vremenske oznake, a u našoj šemi ovaj mehanizam je vrlo teško ispravno implementirati. Stoga smo koristili klasičnu šemu sa brokerom poruka, odnosno sa dispečerom koji distribuira poruke između Risk Enginea.

Drugi problem se odnosio na pristup klijenta: ako postoji nekoliko Risk Gateway-a, klijent se mora povezati sa svakim od njih, a to će zahtijevati promjene na sloju klijenta. Željeli smo pobjeći od ovoga u ovoj fazi, tako da trenutni Risk Gateway dizajn obrađuje cijeli tok podataka. Ovo uvelike ograničava maksimalnu propusnost, ali uvelike pojednostavljuje integraciju sistema.

Umnožavanje

Naš sistem ne bi trebao imati ni jednu tačku kvara, odnosno sve komponente moraju biti duplicirane, uključujući i brokera poruka. Ovaj problem smo riješili korištenjem CLLM sistema: sadrži RCMS klaster u kojem dva dispečera mogu raditi u master-slave modu, a kada jedan otkaže, sistem se automatski prebacuje na drugi.

Rad sa rezervnim data centrom

InfiniBand je optimiziran za rad kao lokalna mreža, odnosno za povezivanje opreme za montažu u stalak, a InfiniBand mreža se ne može postaviti između dva geografski distribuirana data centra. Stoga smo implementirali bridge/dispečer, koji se povezuje na skladište poruka preko običnih Ethernet mreža i prenosi sve transakcije u drugu IB mrežu. Kada trebamo da migriramo iz data centra, možemo izabrati s kojim ćemo podatkovnim centrom sada raditi.

Ishodi

Sve navedeno nije urađeno odjednom, bilo je potrebno nekoliko iteracija razvoja nove arhitekture. Prototip smo napravili za mjesec dana, ali je trebalo više od dvije godine da ga dovedemo u radno stanje. Pokušali smo postići najbolji kompromis između povećanja vremena obrade transakcija i povećanja pouzdanosti sistema.

Pošto je sistem dosta ažuriran, implementirali smo oporavak podataka iz dva nezavisna izvora. Ako skladište poruka iz nekog razloga ne funkcioniše ispravno, možete preuzeti dnevnik transakcija iz drugog izvora - iz Risk Enginea. Ovaj princip se poštuje u cijelom sistemu.

Između ostalog, uspjeli smo sačuvati klijentski API tako da ni brokeri ni bilo ko drugi ne bi zahtijevali značajne izmjene za novu arhitekturu. Morali smo promijeniti neke interfejse, ali nije bilo potrebe za značajnim promjenama u operativnom modelu.

Trenutnu verziju naše platforme nazvali smo Rebus - kao skraćenica za dvije najuočljivije inovacije u arhitekturi, Risk Engine i BUS.

Evolucija arhitekture sistema trgovanja i kliringa Moskovske berze. Dio 2

U početku smo željeli dodijeliti samo klirinški dio, ali rezultat je bio ogroman distribuirani sistem. Klijenti sada mogu komunicirati ili sa Trade Gateway-om, Kliring Gateway-om ili oboje.

Šta smo na kraju postigli:

Evolucija arhitekture sistema trgovanja i kliringa Moskovske berze. Dio 2

Smanjen nivo kašnjenja. Uz mali obim transakcija, sistem radi isto kao i prethodna verzija, ali u isto vrijeme može izdržati mnogo veće opterećenje.

Maksimalni učinak je povećan sa 50 hiljada na 180 hiljada transakcija u sekundi. Dalje povećanje ometa jedini tok usklađivanja naloga.

Postoje dva načina za dalje poboljšanje: paraleliziranje uparivanja i promjena načina na koji radi sa Gateway-om. Sada svi Gateway-i rade prema shemi replikacije, koja pod takvim opterećenjem prestaje normalno funkcionirati.

Na kraju, mogu dati nekoliko savjeta onima koji finaliziraju poslovne sisteme:

  • Budite spremni na najgore u svakom trenutku. Problemi uvijek nastaju neočekivano.
  • Obično je nemoguće brzo prepraviti arhitekturu. Pogotovo ako trebate postići maksimalnu pouzdanost za više indikatora. Što više čvorova, više resursa je potrebno za podršku.
  • Sva prilagođena i vlasnička rješenja zahtijevat će dodatne resurse za istraživanje, podršku i održavanje.
  • Nemojte odlagati rješavanje problema pouzdanosti sistema i oporavka nakon kvarova; uzmite ih u obzir u početnoj fazi dizajna.

izvor: www.habr.com

Dodajte komentar