La evoluo de la arkitekturo de la komerca kaj klarigsistemo de la Moskva Interŝanĝo. Parto 2

La evoluo de la arkitekturo de la komerca kaj klarigsistemo de la Moskva Interŝanĝo. Parto 2

Ĉi tio estas daŭrigo de longa rakonto pri nia dorna vojo al kreado de potenca, alta ŝarĝa sistemo, kiu certigas la funkciadon de la Interŝanĝo. La unua parto estas ĉi tie: habr.com/en/post/444300

Mistera eraro

Post multnombraj provoj, la ĝisdatigita komerca kaj puriga sistemo ekfunkciis, kaj ni renkontis cimon pri kiu ni povus skribi detektivo-mistikan rakonton.

Baldaŭ post lanĉo sur la ĉefa servilo, unu el la transakcioj estis procesita kun eraro. Tamen ĉio estis bone en la rezerva servilo. Montriĝis, ke simpla matematika operacio de kalkulo de la eksponento sur la ĉefa servilo donis negativan rezulton de la reala argumento! Ni daŭrigis nian esploradon, kaj en la SSE2-registro ni trovis diferencon en unu bito, kiu respondecas pri rondigo kiam oni laboras kun glitkomaj nombroj.

Ni skribis simplan testan utilecon por kalkuli la eksponenton kun la rondiga bita aro. Montriĝis, ke en la versio de RedHat Linukso, kiun ni uzis, estis eraro en labori kun la matematika funkcio kiam la malbonŝanca bito estis enmetita. Ni raportis ĉi tion al RedHat, post iom da tempo ni ricevis flikaĵon de ili kaj eligis ĝin. La eraro ne plu okazis, sed ne estis klare, de kie eĉ venis ĉi tiu peco? La funkcio respondecis pri ĝi fesetround el la lingvo C. Ni zorge analizis nian kodon serĉante la supozitan eraron: ni kontrolis ĉiujn eblajn situaciojn; rigardis ĉiujn funkciojn, kiuj uzis rondigon; provis reprodukti malsukcesan sesion; uzis malsamajn kompililojn kun malsamaj opcioj; Statika kaj dinamika analizo estis uzata.

La kaŭzo de la eraro ne estis trovita.

Tiam ili komencis kontroli la aparataron: ili faris ŝarĝtestadon de la procesoroj; kontrolis la RAM; Ni eĉ faris provojn por la tre neverŝajna scenaro de plurbita eraro en unu ĉelo. Sen utilo.

En la fino, ni decidiĝis laŭ teorio de la mondo de altenergia fiziko: iu altenergia partiklo flugis en nian datumcentron, trapikis la kazan muron, trafis la procesoron kaj kaŭzis, ke la ellasilfermilo algluiĝis en tiu sama peco. Ĉi tiu absurda teorio estis nomita la "neŭtrino". Se vi estas malproksime de partikla fiziko: neŭtrinoj preskaŭ ne interagas kun la ekstera mondo, kaj certe ne kapablas influi la funkciadon de la procesoro.

Ĉar ne eblis trovi la kaŭzon de la malsukceso, la "ofenda" servilo estis forigita de operacio ĉiaokaze.

Post iom da tempo, ni komencis plibonigi la varman rezervan sistemon: ni enkondukis tiel nomatajn "varmaj rezervoj" (varmaj) - nesinkronajn kopiojn. Ili ricevis fluon de transakcioj, kiuj povus esti lokitaj en malsamaj datumcentroj, sed varmoj ne aktive interagis kun aliaj serviloj.

La evoluo de la arkitekturo de la komerca kaj klarigsistemo de la Moskva Interŝanĝo. Parto 2

Kial ĉi tio estis farita? Se la rezerva servilo malsukcesas, tiam varme ligita al la ĉefa servilo fariĝas la nova sekurkopio. Tio estas, post fiasko, la sistemo ne restas kun unu ĉefa servilo ĝis la fino de la komerca sesio.

Kaj kiam la nova versio de la sistemo estis provita kaj metita en funkciado, la rondiga bita eraro denove okazis. Krome, kun la pliiĝo de la nombro da varmaj serviloj, la eraro komencis aperi pli ofte. Samtempe, la vendisto havis nenion por montri, ĉar ne estis konkretaj pruvoj.

Dum la sekva analizo de la situacio, ekestis teorio, ke la problemo povus rilati al la OS. Ni skribis simplan programon, kiu vokas funkcion en senfina buklo fesetround, memoras la nunan staton kaj kontrolas ĝin per dormo, kaj tio estas farita en multaj konkurantaj fadenoj. Elektinte la parametrojn por dormo kaj la nombro da fadenoj, ni komencis konstante reprodukti la bitan malsukceson post ĉirkaŭ 5 minutoj da funkciado de la utileco. Tamen, Red Hat-subteno estis nekapabla reprodukti ĝin. Testado de niaj aliaj serviloj montris, ke nur tiuj kun certaj procesoroj estas susceptibles al la eraro. Samtempe, ŝanĝi al nova kerno solvis la problemon. Fine ni simple anstataŭigis la OS, kaj la vera kaŭzo de la cimo restis neklara.

Kaj subite pasintjare aperis artikolo pri Habré "Kiel mi trovis cimon en Intel Skylake-procesoroj" La en ĝi priskribita situacio tre similas al la nia, sed la aŭtoro portis la esploron plu kaj prezentis teorion, ke la eraro estas en la mikrokodo. Kaj kiam Linukso-kernoj estas ĝisdatigitaj, produktantoj ankaŭ ĝisdatigas la mikrokodon.

Pluevoluigo de la sistemo

Kvankam ni forigis la eraron, ĉi tiu rakonto devigis nin rekonsideri la sisteman arkitekturon. Post ĉio, ni ne estis protektitaj kontraŭ la ripeto de tiaj cimoj.

La sekvaj principoj formis la bazon por la venontaj plibonigoj al la rezervadsistemo:

  • Vi ne povas fidi iun ajn. Serviloj eble ne funkcias ĝuste.
  • Plimulta rezervado.
  • Certigante konsenton. Kiel logika aldono al plimulta rezervado.
  • Duoblaj malsukcesoj eblas.
  • Vigleco. La nova varma standby-skemo ne devus esti pli malbona ol la antaŭa. Komercado devus daŭrigi seninterrompe ĝis la lasta servilo.
  • Malgranda pliiĝo en latenteco. Ajna malfunkcio implicas grandegajn financajn perdojn.
  • Minimuma retinterago por konservi latencia kiel eble plej malalta.
  • Elektante novan majstran servilon en sekundoj.

Neniu el la disponeblaj solvoj sur la merkato konvenis al ni, kaj la Raft-protokolo estis ankoraŭ en sia infanaĝo, do ni kreis nian propran solvon.

La evoluo de la arkitekturo de la komerca kaj klarigsistemo de la Moskva Interŝanĝo. Parto 2

Retoj

Krom la rezervosistemo, ni komencis modernigi retan interagadon. La I/O-subsistemo konsistis el multaj procezoj, kiuj havis la plej malbonan efikon al tremo kaj latenteco. Kun centoj da procezoj pritraktantaj TCP-konektojn, ni estis devigitaj konstante ŝanĝi inter ili, kaj je mikrosekunda skalo ĉi tio estas sufiĉe tempopostula operacio. Sed la plej malbona parto estas, ke kiam procezo ricevis pakaĵon por prilaborado, ĝi sendis ĝin al unu SystemV-vico kaj tiam atendis eventon de alia SystemV-vico. Tamen, kiam ekzistas granda nombro da nodoj, la alveno de nova TCP-pako en unu procezo kaj la ricevo de datumoj en la atendovico en alia reprezentas du konkurantajn okazaĵojn por la OS. En ĉi tiu kazo, se ne ekzistas fizikaj procesoroj disponeblaj por ambaŭ taskoj, unu estos procesita, kaj la dua estos metita en atendovicon. Estas neeble antaŭdiri la sekvojn.

En tiaj situacioj, dinamika proceza prioritatkontrolo povas esti uzita, sed tio postulos la uzon de rimed-intensaj sistemvokoj. Kiel rezulto, ni ŝanĝis al unu fadeno uzante klasikan epoll, ĉi tio multe pliigis la rapidecon kaj reduktis la transakcian pretigan tempon. Ni ankaŭ forigis apartajn retkomunikajn procezojn kaj komunikadon per SystemV, signife reduktis la nombron da sistemaj vokoj kaj komencis kontroli la prioritatojn de operacioj. Sur la I/O-subsistemo sole, estis eble ŝpari proksimume 8-17 mikrosekundojn, depende de la scenaro. Ĉi tiu unu-fadena skemo estis uzata senŝanĝa ekde tiam; unu epoll-fadeno kun marĝeno sufiĉas por servi ĉiujn ligojn.

Transakcia Pretigo

La kreskanta ŝarĝo sur nia sistemo postulis ĝisdatigi preskaŭ ĉiujn ĝiajn komponantojn. Sed, bedaŭrinde, stagno en la kresko de procesoraj horloĝrapidoj en la lastaj jaroj ne plu ebligis skali procezojn fronte. Tial ni decidis dividi la Motoran procezon en tri nivelojn, la plej okupata el ili estas la riska kontrola sistemo, kiu taksas la haveblecon de financoj en kontoj kaj kreas la transakciojn mem. Sed mono povas esti en malsamaj valutoj, kaj estis necese eltrovi sur kia bazo la prilaborado de petoj devas esti dividita.

La logika solvo estas dividi ĝin per valuto: unu servilo komercas per dolaroj, alia per funtoj, kaj triono per eŭroj. Sed se, kun tia skemo, du transakcioj estas senditaj por aĉeti malsamajn valutojn, tiam aperos la problemo de malsinkronigo de monujo. Sed sinkronigado estas malfacila kaj multekosta. Sekve, estus ĝuste disigi aparte per monujoj kaj aparte per instrumentoj. Cetere, plej multaj okcidentaj interŝanĝoj ne havas la taskon kontroli riskojn tiel akre kiel ni, do plej ofte ĉi tio estas farata eksterrete. Ni devis efektivigi interretan konfirmon.

Ni klarigu per ekzemplo. Komercisto volas aĉeti $ 30, kaj la peto iras al transakcia validigo: ni kontrolas ĉu ĉi tiu komercisto estas permesita al ĉi tiu komerca reĝimo kaj ĉu li havas la necesajn rajtojn. Se ĉio estas en ordo, la peto iras al la riska kontrola sistemo, t.e. kontroli la sufiĉon de financoj por fini transakcion. Estas noto, ke la bezonata kvanto estas nuntempe blokita. La peto tiam estas plusendita al la komerca sistemo, kiu aprobas aŭ malaprobas la transakcion. Ni diru, ke la transakcio estas aprobita - tiam la riska kontrola sistemo markas, ke la mono estas malblokita, kaj la rubloj iĝas dolaroj.

Ĝenerale, la riska kontrola sistemo enhavas kompleksajn algoritmojn kaj faras grandan kvanton da tre intensaj rimedoj, kaj ne simple kontrolas la "kontan bilancon", kiel ĝi povus ŝajni unuavide.

Kiam ni komencis dividi la Engine-procezon en nivelojn, ni renkontis problemon: la kodo, kiu estis disponebla en tiu tempo, aktive uzis la saman aron da datumoj ĉe la validumaj kaj kontrolaj stadioj, kio postulis reverki la tutan kodbazon. Kiel rezulto, ni pruntis teknikon por prilaborado de instrukcioj de modernaj procesoroj: ĉiu el ili estas dividita en malgrandajn stadiojn kaj pluraj agoj estas faritaj paralele en unu ciklo.

La evoluo de la arkitekturo de la komerca kaj klarigsistemo de la Moskva Interŝanĝo. Parto 2

Post malgranda adapto de la kodo, ni kreis dukton por paralela transakcia prilaborado, en kiu la transakcio estis dividita en 4 stadiojn de la dukto: retinterago, validigo, ekzekuto kaj publikigo de la rezulto.

La evoluo de la arkitekturo de la komerca kaj klarigsistemo de la Moskva Interŝanĝo. Parto 2

Ni rigardu ekzemplon. Ni havas du pretigsistemojn, seriajn kaj paralelajn. La unua transakcio alvenas kaj estas sendita por validigo en ambaŭ sistemoj. La dua transakcio tuj alvenas: en paralela sistemo ĝi estas tuj ekfunkciigita, kaj en sinsekva sistemo ĝi estas metita en atendovico atendante ke la unua transakcio trapasos la nunan pretigan etapon. Tio estas, la ĉefa avantaĝo de dukto prilaborado estas, ke ni prilaboras la transakcian vicon pli rapide.

Jen kiel ni elpensis la ASTS+-sistemon.

Vere, ankaŭ ne ĉio estas tiel glata kun transportiloj. Ni diru, ke ni havas transakcion, kiu influas datumajn tabelojn en najbara transakcio; ĉi tio estas tipa situacio por interŝanĝo. Tia transakcio ne povas esti efektivigita en dukto ĉar ĝi povas influi aliajn. Ĉi tiu situacio estas nomita datuma danĝero, kaj tiaj transakcioj estas simple procesitaj aparte: kiam la "rapidaj" transakcioj en la atendovico finiĝas, la dukto ĉesas, la sistemo prilaboras la "malrapidan" transakcion, kaj poste komencas la dukton denove. Feliĉe, la proporcio de tiaj transakcioj en la ĝenerala fluo estas tre malgranda, do la dukto haltas tiel malofte, ke ĝi ne influas ĝeneralan rendimenton.

La evoluo de la arkitekturo de la komerca kaj klarigsistemo de la Moskva Interŝanĝo. Parto 2

Tiam ni komencis solvi la problemon sinkronigi tri fadenojn de ekzekuto. La rezulto estis sistemo bazita sur ringa bufro kun fiksgrandaj ĉeloj. En ĉi tiu sistemo, ĉio estas kondiĉigita de pretiga rapideco; datumoj ne estas kopiitaj.

  • Ĉiuj alvenantaj retpakoj eniras la asignostadion.
  • Ni metas ilin en tabelon kaj markas ilin kiel disponeblaj por la etapo #1.
  • La dua transakcio alvenis, ĝi denove disponeblas por la etapo n-ro 1.
  • La unua pretiga fadeno vidas la disponeblajn transakciojn, prilaboras ilin kaj movas ilin al la sekva etapo de la dua pretiga fadeno.
  • Ĝi tiam prilaboras la unuan transakcion kaj markas la respondan ĉelon deleted — ĝi nun disponeblas por nova uzo.

La tuta vico estas prilaborita tiamaniere.

La evoluo de la arkitekturo de la komerca kaj klarigsistemo de la Moskva Interŝanĝo. Parto 2

Pretigo de ĉiu stadio prenas unuojn aŭ dekojn de mikrosekundoj. Kaj se ni uzas normajn OS-sinkronigajn skemojn, tiam ni perdos pli da tempo pri la sinkronigado mem. Tial ni komencis uzi spinlock. Tamen ĉi tio estas tre malbona en realtempa sistemo, kaj RedHat strikte ne rekomendas fari tion, do ni aplikas spinŝlosilon dum 100 ms, kaj poste ŝanĝas al semaforreĝimo por forigi la eblecon de blokiĝo.

Kiel rezulto, ni atingis agadon de ĉirkaŭ 8 milionoj da transakcioj por sekundo. Kaj laŭvorte du monatojn poste en artikolo pri LMAX Disruptor ni vidis priskribon de cirkvito kun la sama funkcieco.

La evoluo de la arkitekturo de la komerca kaj klarigsistemo de la Moskva Interŝanĝo. Parto 2

Nun povus esti pluraj fadenoj de ekzekuto en unu etapo. Ĉiuj transakcioj estis procesitaj unu post alia, en la ordo en kiu ili estis ricevitaj. Kiel rezulto, pinta rendimento pliiĝis de 18 mil al 50 mil transakcioj por sekundo.

Sistemo de administrado de risko de interŝanĝo

Ne estas limo al perfekteco, kaj baldaŭ ni rekomencis modernigon: kadre de ASTS+, ni komencis movi sistemojn pri administrado de risko kaj operaciaj sistemoj en aŭtonomajn komponantojn. Ni evoluigis flekseblan modernan arkitekturon kaj novan hierarkian riskan modelon, kaj provis uzi la klason kie ajn ebla fixed_point anstataŭ double.

Sed tuj aperis problemo: kiel sinkronigi la tutan komercan logikon, kiu funkcias de multaj jaroj kaj translokigi ĝin al la nova sistemo? Kiel rezulto, la unua versio de la prototipo de la nova sistemo devis esti forlasita. La dua versio, kiu nuntempe funkcias en produktado, baziĝas sur la sama kodo, kiu funkcias kaj en la komercaj kaj riskaj partoj. Dum evoluo, la plej malfacila afero estis git merge inter du versioj. Nia samideano Evgenij Mazurenok faris ĉi tiun operacion ĉiusemajne kaj ĉiufoje li malbenis tre longe.

Elektinte novan sistemon, ni tuj devis solvi la problemon de interago. Elektinte datuman buson, necesis certigi stabilan tremiĝon kaj minimuman latentecon. La reto InfiniBand RDMA plej taŭgas por ĉi tio: la averaĝa pretigtempo estas 4 fojojn malpli ol en 10 G Ethernet-retoj. Sed kio vere allogis nin estis la diferenco en procentoj - 99 kaj 99,9.

Kompreneble, InfiniBand havas siajn defiojn. Unue, malsama API - ibverbs anstataŭ ingoj. Due, preskaŭ ne ekzistas vaste disponeblaj malfermfontaj mesaĝaj solvoj. Ni provis fari nian propran prototipon, sed ĝi montriĝis tre malfacila, do ni elektis komercan solvon - Confinity Low Latency Messaging (antaŭe IBM MQ LLM).

Tiam ekestis la tasko ĝuste dividi la riskan sistemon. Se vi simple forigas la Riskan Motoron kaj ne kreas mezan nodon, tiam transakcioj de du fontoj povas esti miksitaj.

La evoluo de la arkitekturo de la komerca kaj klarigsistemo de la Moskva Interŝanĝo. Parto 2

La tiel nomataj Ultra Low Latency-solvoj havas reordigan reĝimon: transakcioj de du fontoj povas esti aranĝitaj en la bezonata ordo post ricevo; tio estas efektivigita per aparta kanalo por interŝanĝi informojn pri la mendo. Sed ni ankoraŭ ne uzas ĉi tiun reĝimon: ĝi komplikas la tutan procezon, kaj en kelkaj solvoj ĝi tute ne estas subtenata. Krome, al ĉiu transakcio devus esti asignita respondaj tempomarkoj, kaj en nia skemo ĉi tiu mekanismo estas tre malfacile efektivigi ĝuste. Tial ni uzis la klasikan skemon kun mesaĝmakleristo, tio estas, kun sendanto, kiu distribuas mesaĝojn inter la Risk Engine.

La dua problemo estis rilata al klienta aliro: se ekzistas pluraj Risk Gateways, la kliento devas konekti al ĉiu el ili, kaj ĉi tio postulos ŝanĝojn al la klienta tavolo. Ni volis foriri de ĉi tio en ĉi tiu etapo, do la nuna Risk Gateway-dezajno prilaboras la tutan datumfluon. Tio tre limigas la maksimuman trairon, sed tre simpligas sisteman integriĝon.

Duobligo

Nia sistemo ne havu ununuran punkton de fiasko, tio estas, ĉiuj komponantoj devas esti duobligitaj, inkluzive de la mesaĝmakleristo. Ni solvis ĉi tiun problemon uzante la CLLM-sistemon: ĝi enhavas RCMS-areton en kiu du sendantoj povas labori en majstra-sklava reĝimo, kaj kiam unu malsukcesas, la sistemo aŭtomate ŝanĝas al la alia.

Laborante kun rezerva datumcentro

InfiniBand estas optimumigita por funkciado kiel loka reto, tio estas, por konekti rako-muntan ekipaĵon, kaj InfiniBand-reto ne povas esti metita inter du geografie distribuitaj datumcentroj. Tial, ni efektivigis ponton/sendilon, kiu konektas al la mesaĝstokado per regulaj Eterretaj retoj kaj relajas ĉiujn transakciojn al dua IB-reto. Kiam ni devas migri de datumcentro, ni povas elekti kun kiu datumcentro labori nun.

Rezultoj

Ĉio ĉi-supra ne estis farita tuj; necesis plurajn ripetojn por evoluigi novan arkitekturon. Ni kreis la prototipon en unu monato, sed daŭris pli ol du jarojn por ke ĝi funkciigu. Ni provis atingi la plej bonan kompromison inter pliigado de transakcia pretigotempo kaj pliigo de sistema fidindeco.

Ĉar la sistemo estis ege ĝisdatigita, ni efektivigis datuman reakiron de du sendependaj fontoj. Se la mesaĝvendejo ne funkcias ĝuste ial, vi povas preni la transakcian protokolon de dua fonto - de la Riskmotoro. Ĉi tiu principo estas observata ĉie en la sistemo.

Interalie, ni povis konservi la klientan API por ke nek makleristoj nek iu ajn alia postulus gravan relaboron por la nova arkitekturo. Ni devis ŝanĝi kelkajn interfacojn, sed ne necesis fari signifajn ŝanĝojn al la mastruma modelo.

Ni nomis la nunan version de nia platformo Rebus - kiel mallongigo por la du plej rimarkindaj novigoj en la arkitekturo, Risk Engine kaj BUS.

La evoluo de la arkitekturo de la komerca kaj klarigsistemo de la Moskva Interŝanĝo. Parto 2

Komence, ni volis asigni nur la malbaran parton, sed la rezulto estis grandega distribuita sistemo. Klientoj nun povas interagi aŭ kun la Komerca Enirejo, la Clearing Gateway, aŭ ambaŭ.

Kion ni finfine atingis:

La evoluo de la arkitekturo de la komerca kaj klarigsistemo de la Moskva Interŝanĝo. Parto 2

Reduktis la latentecnivelon. Kun malgranda volumo de transakcioj, la sistemo funkcias same kiel la antaŭa versio, sed samtempe povas elteni multe pli altan ŝarĝon.

Pinta rendimento pliiĝis de 50 mil al 180 mil transakcioj por sekundo. Plia pliiĝo estas malhelpita de la sola fluo de ordo-kongruo.

Estas du manieroj por plia plibonigo: paraleligi kongruon kaj ŝanĝi la manieron kiel ĝi funkcias kun Gateway. Nun ĉiuj Enirejoj funkcias laŭ reproduktadskemo, kiu, sub tia ŝarĝo, ĉesas funkcii normale.

Fine, mi povas doni kelkajn konsilojn al tiuj, kiuj finfinas entreprenajn sistemojn:

  • Estu preta por la plej malbona ĉiam. Problemoj ĉiam aperas neatendite.
  • Estas kutime neeble rapide refari arkitekturon. Precipe se vi bezonas atingi maksimuman fidindecon tra pluraj indikiloj. Ju pli da nodoj, des pli da rimedoj necesas por subteno.
  • Ĉiuj kutimaj kaj proprietaj solvoj postulos pliajn rimedojn por esplorado, subteno kaj prizorgado.
  • Ne prokrastu solvi problemojn pri sistema fidindeco kaj reakiro post misfunkciadoj; konsideru ilin en la komenca fazo de dezajno.

fonto: www.habr.com

Aldoni komenton