Moskva börsi kauplemis- ja arveldussüsteemi arhitektuuri areng. 1. osa

Moskva börsi kauplemis- ja arveldussüsteemi arhitektuuri areng. 1. osa

Tere kõigile! Minu nimi on Sergei Kostanbaev, arendan Börsil kauplemissüsteemi tuuma.

Kui Hollywoodi filmides näidatakse New Yorgi börsi, näeb see alati välja nii: rahvamassid, kõik karjuvad midagi, lehvitavad paberitega, toimub täielik kaos. Seda pole siin Moskva börsil kunagi juhtunud, sest kauplemine on algusest peale toimunud elektrooniliselt ja põhineb kahel põhiplatvormil - Spectra (forex market) ja ASTS (välisvaluuta, aktsia- ja rahaturg). Ja täna tahan rääkida ASTS-i kauplemis- ja arveldussüsteemi arhitektuuri arengust, erinevatest lahendustest ja leidudest. Lugu tuleb pikk, nii et pidin selle kaheks osaks jagama.

Oleme üks väheseid börse maailmas, mis kaupleb igat liiki varadega ja pakub täielikku valikut börsiteenuseid. Näiteks eelmisel aastal olime maailmas teisel kohal võlakirjade kauplemismahu poolest, 25. kohal kõigi börside seas, 13. kohal kapitalisatsioonilt avalike börside seas.

Moskva börsi kauplemis- ja arveldussüsteemi arhitektuuri areng. 1. osa

Professionaalsete kauplemisosaliste jaoks on sellised parameetrid nagu reaktsiooniaeg, ajajaotuse stabiilsus (värinad) ja kogu kompleksi töökindlus kriitilise tähtsusega. Praegu töötleme kümneid miljoneid tehinguid päevas. Iga tehingu töötlemine süsteemituuma poolt võtab kümneid mikrosekundeid. Muidugi on mobiilsideoperaatoritel aastavahetusel või otsingumootoritel endil suurem töökoormus kui meil, kuid töökoormuse osas koos ülalnimetatud omadustega on minu arvates vähesed meiega võrreldavad. Samas on meie jaoks oluline, et süsteem ei aeglustuks hetkekski, töötaks absoluutselt stabiilselt ning kõik kasutajad oleksid võrdsel tasemel.

Natuke ajalugu

1994. aastal käivitati Moskva pankadevahelisel valuutabörsil (MICEX) Austraalia ASTS-süsteem ja sellest hetkest alates saab lugeda Venemaa elektroonilise kauplemise ajalugu. 1998. aastal moderniseeriti börsi arhitektuur, et võtta kasutusele Interneti-kauplemine. Sellest ajast alates on uute lahenduste juurutamise kiirus ja arhitektuursed muudatused kõigis süsteemides ja alamsüsteemides ainult hoogu kogunud.

Neil aastatel töötas vahetussüsteem tipptasemel riistvaral – ülimalt töökindlatel HP Superdome 9000 serveritel (ehitatud PA-RISC), milles oli dubleeritud absoluutselt kõik: sisendi/väljundi alamsüsteemid, võrk, RAM (tegelikult oli RAM-i massiiv RAID), protsessorid (kuumvahetusega). Iga serveri komponenti oli võimalik muuta ilma masinat peatamata. Toetusime nendele seadmetele ja pidasime neid peaaegu tõrkekindlateks. Operatsioonisüsteemiks oli Unixi sarnane HP UX-süsteem.

Kuid alates umbes 2010. aastast on tekkinud nähtus, mida nimetatakse kõrgsageduslikuks kauplemiseks (HFT) või kõrgsageduskauplemiseks – lihtsamalt öeldes börsirobotid. Vaid 2,5 aastaga on meie serverite koormus kasvanud 140 korda.

Moskva börsi kauplemis- ja arveldussüsteemi arhitektuuri areng. 1. osa

Vana arhitektuuri ja tehnikaga polnud sellist koormust võimalik taluda. Oli vaja kuidagi kohaneda.

Algus

Vahetussüsteemile suunatud taotlused võib jagada kahte tüüpi:

  • Tehingud. Kui soovite osta dollareid, aktsiaid või midagi muud, saadate tehingu kauplemissüsteemi ja saate vastuse edu kohta.
  • Teabenõuded. Kui soovite teada saada hetkehinda, vaadake tellimuste raamatut või indekseid, seejärel saatke teabepäringud.

Moskva börsi kauplemis- ja arveldussüsteemi arhitektuuri areng. 1. osa

Skemaatiliselt võib süsteemi tuuma jagada kolmeks tasemeks:

  • Klienditasand, millel maaklerid ja kliendid töötavad. Nad kõik suhtlevad juurdepääsuserveritega.
  • Lüüsiserverid on vahemällu salvestavad serverid, mis töötlevad kohapeal kõiki teabepäringuid. Kas soovite teada, mis hinnaga Sberbanki aktsiad praegu kauplevad? Päring läheb juurdepääsuserverisse.
  • Kui aga tahad aktsiaid osta, siis läheb päring keskserverisse (Trade Engine). Iga turutüübi jaoks on üks selline server, neil on oluline roll, nende jaoks oleme selle süsteemi loonud.

Kauplemissüsteemi tuumaks on nutikas mälusisene andmebaas, milles kõik tehingud on börsitehingud. Alus oli kirjutatud C-keeles, ainsad välised sõltuvused olid libc-teek ja dünaamilist mälujaotust polnud üldse. Töötlemisaja vähendamiseks alustab süsteem staatilise massiivikomplekti ja andmete staatilise ümberpaigutusega: esmalt laaditakse kõik jooksva päeva andmed mällu ja edasist kettale juurdepääsu ei tehta, kogu töö toimub ainult mälus. Kui süsteem käivitub, on kõik viiteandmed juba sorteeritud, nii et otsing töötab väga tõhusalt ja võtab käitusajal vähe aega. Kõik tabelid on tehtud pealetükkivate loendite ja dünaamiliste andmestruktuuride puudega, nii et need ei vaja käitusajal mälu eraldamist.

Vaatame lühidalt meie kauplemis- ja arveldussüsteemi arengulugu.
Kauplemis- ja arveldussüsteemi arhitektuuri esimene versioon oli üles ehitatud nn Unixi interaktsioonile: kasutati ühismälu, semafoore ja järjekordi ning iga protsess koosnes ühest lõimest. Selline lähenemine oli laialt levinud 1990. aastate alguses.

Süsteemi esimene versioon sisaldas kahte Gateway taset ja kauplemissüsteemi keskserverit. Töö käik oli selline:

  • Klient saadab päringu, mis jõuab väravani. See kontrollib vormingu kehtivust (kuid mitte andmeid ennast) ja lükkab tagasi valed tehingud.
  • Kui teabepäring on saadetud, täidetakse see kohapeal; kui me räägime tehingust, siis see suunatakse keskserverisse.
  • Seejärel töötleb kauplemismootor tehingut, muudab kohalikku mälu ning saadab tehingule ja tehingule vastuse replikatsiooniks, kasutades eraldi replikatsioonimootorit.
  • Gateway saab vastuse kesksõlmelt ja edastab selle kliendile.
  • Mõne aja pärast võtab lüüs tehingu vastu replikatsioonimehhanismi kaudu ja seekord teostab selle lokaalselt, muutes oma andmestruktuure nii, et järgmised teabepäringud kuvavad uusimaid andmeid.

Tegelikult kirjeldab see replikatsioonimudelit, milles Gateway kordas täielikult kauplemissüsteemis tehtud toiminguid. Eraldi replikatsioonikanal tagas tehingute teostamise samas järjekorras mitmes juurdepääsusõlmes.

Kuna kood oli ühelõimeline, kasutati paljude klientide teenindamiseks klassikalist protsessikahvlitega skeemi. Kogu andmebaasi harutamine oli aga väga kulukas, mistõttu kasutati kergeid teenuseprotsesse, mis kogusid TCP-seanssidest pakette ja kandsid need ühte järjekorda (SystemV Message Queue). Gateway ja Trade Engine töötasid ainult selle järjekorraga, võttes sealt tehinguid täitmiseks. Sellele ei saanud enam vastust saata, kuna polnud selge, milline teenindusprotsess seda lugema peaks. Seega võtsime kasutusele nipi: iga hargnenud protsess lõi enda jaoks vastusejärjekorra ja kui päring saabus sissetulevasse järjekorda, lisati sellele kohe vastusejärjekorra silt.

Pidev suurte andmemahtude kopeerimine järjekorrast järjekorda tekitas probleeme, mis on eriti tüüpilised teabepäringutele. Seetõttu kasutasime teist nippi: lisaks vastusejärjekorrale lõi iga protsess ka ühismälu (SystemV Shared Memory). Pakid ise pandi sinna sisse ja järjekorda hoiti vaid silt, mis võimaldas leida originaalpakendi. See aitas andmeid salvestada protsessori vahemällu.

SystemV IPC sisaldab utiliite järjekorra, mälu ja semaforobjektide oleku vaatamiseks. Kasutasime seda aktiivselt, et mõista, mis konkreetsel hetkel süsteemis toimus, kuhu paketid kogunesid, mis blokeeriti jne.

Esimesed moderniseerimised

Esiteks vabanesime ühe protsessiga Gatewayst. Selle oluline puudus oli see, et see suutis käsitleda kas ühte replikatsioonitehingut või ühe kliendi teabepäringut. Koormuse kasvades võtab Gateway taotluste töötlemiseks kauem aega ja ta ei saa replikatsioonivoogu töödelda. Lisaks, kui klient saatis tehingu, siis tuleb vaid kontrollida selle kehtivust ja edasi saata. Seetõttu asendasime ühe lüüsi protsessi mitme komponendiga, mis võivad töötada paralleelselt: mitme lõimega teave ja tehinguprotsessid, mis töötavad üksteisest sõltumatult jagatud mälualal, kasutades RW-lukustust. Ja samal ajal tutvustasime saatmis- ja replikatsiooniprotsesse.

Kõrgsagedusliku kauplemise mõju

Arhitektuuri ülaltoodud versioon eksisteeris kuni 2010. aastani. Vahepeal ei olnud me enam rahul HP Superdome'i serverite jõudlusega. Lisaks oli PA-RISC arhitektuur praktiliselt surnud; müüja ei pakkunud olulisi uuendusi. Selle tulemusena hakkasime HP UX/PA RISC-lt üle minema Linux/x86-le. Üleminek algas juurdepääsuserverite kohandamisega.

Miks pidime taas arhitektuuri muutma? Fakt on see, et kõrgsageduskauplemine on oluliselt muutnud süsteemi tuuma koormusprofiili.

Oletame, et meil on väike tehing, mis põhjustas olulise hinnamuutuse – keegi ostis pool miljardit dollarit. Paari millisekundi pärast märkavad seda kõik turuosalised ja hakkavad korrektsiooni tegema. Loomulikult on taotlused tohutus järjekorras, mille tühjendamine võtab süsteemil kaua aega.

Moskva börsi kauplemis- ja arveldussüsteemi arhitektuuri areng. 1. osa

Selle 50 ms intervalliga on keskmine kiirus umbes 16 tuhat tehingut sekundis. Kui vähendame akent 20 ms-ni, saame keskmiseks kiiruseks 90 tuhat tehingut sekundis, kusjuures tipphetkel on 200 tuhat tehingut. Teisisõnu, koormus ei ole konstantne, äkiliste puhangutega. Ja taotluste järjekord tuleb alati kiiresti töödelda.

Aga miks üldse järjekord on? Seega märkasid meie näites paljud kasutajad hinnamuutust ja saatsid tehinguid vastavalt. Nad tulevad Gatewaysse, see serialiseerib need, seab kindla järjestuse ja saadab need võrku. Ruuterid segavad pakette ja edastavad need edasi. Kelle pakk esimesena saabus, see tehing "võitis". Selle tulemusena hakkasid börsikliendid märkama, et kui sama tehing saadeti mitmest Gatewayst, siis selle kiire töötlemise võimalused suurenesid. Peagi hakkasid vahetusrobotid Gatewayd taotlustega pommitama ja tekkis tehingute laviin.

Moskva börsi kauplemis- ja arveldussüsteemi arhitektuuri areng. 1. osa

Uus evolutsiooni ring

Pärast põhjalikku testimist ja uurimistööd läksime üle reaalajas operatsioonisüsteemi tuumale. Selleks valisime RedHat Enterprise MRG Linuxi, kus MRG tähistab sõnumside reaalajas võrku. Reaalajas paikade eeliseks on see, et need optimeerivad süsteemi võimalikult kiireks täitmiseks: kõik protsessid on reastatud FIFO järjekorda, tuumad saab isoleerida, ei väljutata, kõiki tehinguid töödeldakse ranges järjekorras.

Moskva börsi kauplemis- ja arveldussüsteemi arhitektuuri areng. 1. osa
Punane - töötab järjekorraga tavalises tuumas, roheline - töötab reaalajas tuumas.

Kuid madala latentsusaja saavutamine tavalistes serverites pole nii lihtne:

  • SMI-režiim, mis on x86 arhitektuuris oluliste välisseadmetega töötamise aluseks, segab oluliselt. Kõikvõimalike riistvarasündmuste töötlemine ning komponentide ja seadmete haldamine toimub püsivara poolt nn läbipaistvas SMI režiimis, milles operatsioonisüsteem ei näe üldse, mida püsivara teeb. Reeglina pakuvad kõik suuremad müüjad püsivaraserveritele spetsiaalseid laiendusi, mis võimaldavad vähendada SMI-töötluse mahtu.
  • Protsessori sagedust ei tohiks dünaamiliselt juhtida, see toob kaasa täiendava seisaku.
  • Kui failisüsteemi logi kustutatakse, toimuvad kernelis teatud protsessid, mis põhjustavad ettearvamatuid viivitusi.
  • Peate pöörama tähelepanu sellistele asjadele nagu CPU afiinsus, katkestuse afiinsus, NUMA.

Pean ütlema, et Linuxi riistvara ja tuuma reaalajas töötlemiseks seadistamise teema väärib eraldi artiklit. Enne hea tulemuse saavutamist kulutasime palju aega katsetamisele ja uurimisele.

PA-RISC-serveritelt x86-le üle minnes me süsteemikoodi praktiliselt väga muutma ei pidanud, vaid kohandasime ja konfigureerisime ümber. Samal ajal parandasime mitu viga. Näiteks ilmnesid kiiresti tagajärjed, et PA RISC oli Big Endian süsteem ja x86 oli Little Endian süsteem: näiteks loeti andmeid valesti. Keerulisem viga oli see, mida PA RISC kasutab järjekindlalt järjekindel (Järjestikku järjekindel) mälujuurdepääs, samas kui x86 saab lugemistoiminguid ümber korraldada, nii et ühel platvormil absoluutselt kehtiv kood läks teisel katki.

Pärast x86-le üleminekut kasvas jõudlus peaaegu kolm korda, keskmine tehingute töötlemise aeg vähenes 60 μs-ni.

Vaatame nüüd lähemalt, millised olulised muudatused on süsteemi arhitektuuris tehtud.

Kuum reserveepos

Kaubaserveritele üle minnes olime teadlikud, et need on vähem töökindlad. Seetõttu eeldasime uue arhitektuuri loomisel a priori ühe või mitme sõlme rikke võimalust. Seetõttu oli vaja kuuma ooterežiimi süsteemi, mis saaks väga kiiresti lülituda varumasinatele.

Lisaks olid muud nõuded:

  • Töödeldud tehinguid ei tohi mingil juhul kaotada.
  • Süsteem peab olema meie infrastruktuuri jaoks täiesti läbipaistev.
  • Kliendid ei tohiks näha katkenud ühendusi.
  • Broneeringud ei tohiks põhjustada olulisi viivitusi, kuna see on vahetuse jaoks kriitiline tegur.

Kuuma ooterežiimi süsteemi loomisel ei pidanud me selliseid stsenaariume topelttõrgeteks (näiteks ühe serveri võrk lakkas töötamast ja põhiserver hangus); ei arvestanud tarkvaras esinevate vigade võimalusega, kuna need tuvastatakse testimise käigus; ja ei võtnud arvesse riistvara ebaõiget tööd.

Selle tulemusena jõudsime järgmise skeemini:

Moskva börsi kauplemis- ja arveldussüsteemi arhitektuuri areng. 1. osa

  • Põhiserver suhtles otse lüüsiserveritega.
  • Kõik põhiserveris vastuvõetud tehingud kopeeriti koheselt eraldi kanali kaudu varuserverisse. Vahekohtunik (kuberner) koordineeris probleemide ilmnemisel ümberlülitamist.

    Moskva börsi kauplemis- ja arveldussüsteemi arhitektuuri areng. 1. osa

  • Peaserver töötles iga tehingut ja ootas varuserveri kinnitust. Latentsuse minimeerimiseks vältisime tehingu lõpuleviimise ootamist varuserveris. Kuna aeg, mis kulus tehingu liikumiseks üle võrgu, oli võrreldav täitmise ajaga, ei lisatud täiendavat latentsust.
  • Saime kontrollida ainult eelmise tehingu põhi- ja varuserveri töötlemise olekut ning praeguse tehingu töötlemise olek oli teadmata. Kuna kasutasime endiselt ühe lõimega protsesse, oleks Backupi vastuse ootamine kogu töötlemisvoogu aeglustanud, mistõttu tegime mõistliku kompromissi: kontrollisime eelmise tehingu tulemust.

Moskva börsi kauplemis- ja arveldussüsteemi arhitektuuri areng. 1. osa

Skeem töötas järgmiselt.

Oletame, et põhiserver lõpetab reageerimise, kuid lüüsid jätkavad suhtlemist. Varuserveril tekib ajalõpp, see võtab ühendust kuberneriga, kes määrab talle põhiserveri rolli ja kõik lüüsid lülituvad uuele põhiserverile.

Kui põhiserver tuleb uuesti võrku, käivitab see ka sisemise ajalõpu, kuna teatud aja jooksul pole Gatewayst serverisse helistatud. Seejärel pöördub ta ka kuberneri poole ja ta jätab ta skeemist välja. Sellest tulenevalt töötab börs ühe serveriga kuni kauplemisperioodi lõpuni. Kuna serveri rikke tõenäosus on üsna väike, peeti seda skeemi üsna vastuvõetavaks, see ei sisaldanud keerulist loogikat ja seda oli lihtne testida.

Et jätkata.

Allikas: www.habr.com

Lisa kommentaar