Evolucioni i arkitekturës së sistemit të tregtimit dhe pastrimit të Bursës së Moskës. Pjesa 2

Evolucioni i arkitekturës së sistemit të tregtimit dhe pastrimit të Bursës së Moskës. Pjesa 2

Ky është një vazhdim i një historie të gjatë për rrugën tonë të mprehtë drejt krijimit të një sistemi të fuqishëm, me ngarkesë të lartë që siguron funksionimin e Exchange. Pjesa e parë është këtu: habr.com/en/post/444300

Gabim misterioz

Pas testeve të shumta, sistemi i përditësuar i tregtimit dhe kleringut u vu në funksion dhe ne u përballëm me një gabim për të cilin mund të shkruanim një histori detektive-mistike.

Menjëherë pas nisjes në serverin kryesor, një nga transaksionet u përpunua me një gabim. Sidoqoftë, gjithçka ishte në rregull në serverin rezervë. Doli që një operacion i thjeshtë matematikor i llogaritjes së eksponentit në serverin kryesor dha një rezultat negativ nga argumenti real! Ne vazhduam kërkimin tonë dhe në regjistrin SSE2 gjetëm një ndryshim në një bit, i cili është përgjegjës për rrumbullakimin kur punoni me numrat me pikë lundruese.

Ne kemi shkruar një mjet të thjeshtë testimi për të llogaritur eksponentin me grupin e biteve të rrumbullakosura. Doli që në versionin e RedHat Linux që përdorëm, kishte një gabim në punën me funksionin matematikor kur u fut biti i pafat. Ne e raportuam këtë në RedHat, pas një kohe morëm një patch prej tyre dhe e shpërndamë atë. Gabimi nuk ndodhi më, por ishte e paqartë se nga erdhi kjo pjesë? Funksioni ishte përgjegjës për të fesetround nga gjuha C. Ne analizuam me kujdes kodin tonë në kërkim të gabimit të supozuar: kontrolluam të gjitha situatat e mundshme; shikoi të gjitha funksionet që përdorën rrumbullakosje; u përpoq të riprodhonte një seancë të dështuar; përdori përpilues të ndryshëm me opsione të ndryshme; Janë përdorur analiza statike dhe dinamike.

Shkaku i gabimit nuk u gjet.

Pastaj ata filluan të kontrollonin harduerin: ata kryen testimin e ngarkesës së procesorëve; kontrolloi RAM-in; Ne madje bëmë teste për skenarin shumë të pamundur të një gabimi me shumë bit në një qelizë. Pa dobi.

Në fund, ne u vendosëm në një teori nga bota e fizikës me energji të lartë: disa grimca me energji të lartë fluturuan në qendrën tonë të të dhënave, shpuan murin e kasës, goditën procesorin dhe shkaktuan që kyçja e këmbëzës të ngjitej në atë pjesë. Kjo teori absurde u quajt "neutrino". Nëse jeni larg fizikës së grimcave: neutrinot pothuajse nuk ndërveprojnë me botën e jashtme dhe sigurisht nuk janë në gjendje të ndikojnë në funksionimin e procesorit.

Meqenëse nuk ishte e mundur të gjehej shkaku i dështimit, serveri "ofendues" u hoq nga funksionimi për çdo rast.

Pas ca kohësh, filluam të përmirësojmë sistemin rezervë të nxehtë: kemi prezantuar të ashtuquajturat "rezerva të ngrohta" (të ngrohta) - kopje asinkrone. Ata morën një rrjedhë transaksionesh që mund të vendoseshin në qendra të ndryshme të të dhënave, por ngrohja nuk ndërvepronte në mënyrë aktive me serverët e tjerë.

Evolucioni i arkitekturës së sistemit të tregtimit dhe pastrimit të Bursës së Moskës. Pjesa 2

Pse u bë kjo? Nëse serveri rezervë dështon, atëherë ngrohja e lidhur me serverin kryesor bëhet rezervimi i ri. Kjo do të thotë, pas një dështimi, sistemi nuk mbetet me një server kryesor deri në fund të seancës së tregtimit.

Dhe kur versioni i ri i sistemit u testua dhe u vu në funksionim, përsëri ndodhi gabimi i bitit të rrumbullakosjes. Për më tepër, me rritjen e numrit të serverëve të ngrohtë, gabimi filloi të shfaqej më shpesh. Në të njëjtën kohë, shitësi nuk kishte asgjë për të treguar, pasi nuk kishte prova konkrete.

Gjatë analizës tjetër të situatës, u ngrit një teori që problemi mund të lidhej me OS. Ne kemi shkruar një program të thjeshtë që thërret një funksion në një lak të pafund fesetround, kujton gjendjen aktuale dhe e kontrollon atë përmes gjumit, dhe kjo bëhet në shumë tema konkurruese. Pasi zgjodhëm parametrat për gjumë dhe numrin e fijeve, filluam të riprodhojmë vazhdimisht dështimin e bitit pas rreth 5 minutash të funksionimit të programit. Sidoqoftë, mbështetja e Red Hat nuk ishte në gjendje ta riprodhonte atë. Testimi i serverëve tanë të tjerë ka treguar se vetëm ata me procesorë të caktuar janë të ndjeshëm ndaj gabimit. Në të njëjtën kohë, kalimi në një kernel të ri e zgjidhi problemin. Në fund, ne thjesht zëvendësuam OS dhe shkaku i vërtetë i defektit mbeti i paqartë.

Dhe befas vitin e kaluar një artikull u botua në Habré "Si gjeta një gabim në procesorët Intel Skylake" Situata e përshkruar në të ishte shumë e ngjashme me tonën, por autori e çoi hetimin më tej dhe parashtroi një teori se gabimi ishte në mikrokod. Dhe kur kernelet e Linux përditësohen, prodhuesit gjithashtu përditësojnë mikrokodin.

Zhvillimi i mëtejshëm i sistemit

Edhe pse e hoqëm gabimin, kjo histori na detyroi të rishqyrtojmë arkitekturën e sistemit. Në fund të fundit, ne nuk ishim të mbrojtur nga përsëritja e gabimeve të tilla.

Parimet e mëposhtme formuan bazën për përmirësimet e radhës në sistemin e rezervimeve:

  • Nuk mund t'i besosh askujt. Serverët mund të mos funksionojnë siç duhet.
  • Rezervimi i shumicës.
  • Sigurimi i konsensusit. Si një shtesë logjike për rezervimin e shumicës.
  • Dështimet e dyfishta janë të mundshme.
  • Vitaliteti. Skema e re e gatishmërisë së nxehtë nuk duhet të jetë më e keqe se ajo e mëparshme. Tregtimi duhet të vazhdojë pa ndërprerje deri në serverin e fundit.
  • Rritje e lehtë e vonesës. Çdo ndërprerje sjell humbje të mëdha financiare.
  • Ndërveprim minimal i rrjetit për të mbajtur vonesën sa më të ulët të jetë e mundur.
  • Zgjedhja e një serveri të ri master në sekonda.

Asnjë nga zgjidhjet e disponueshme në treg nuk na përshtatej dhe protokolli Raft ishte ende në fillimet e tij, kështu që ne krijuam zgjidhjen tonë.

Evolucioni i arkitekturës së sistemit të tregtimit dhe pastrimit të Bursës së Moskës. Pjesa 2

Rrjetëzimi

Përveç sistemit të rezervimit, ne filluam modernizimin e ndërveprimit në rrjet. Nënsistemi I/O përbëhej nga shumë procese, të cilat patën ndikimin më të keq në nervozizëm dhe vonesë. Me qindra procese që trajtojnë lidhjet TCP, ne u detyruam të kalonim vazhdimisht midis tyre, dhe në një shkallë mikrosekondi ky është një operacion mjaft kohë. Por pjesa më e keqe është se kur një proces merr një paketë për përpunim, ai e dërgoi atë në një radhë SystemV dhe më pas priste një ngjarje nga një radhë tjetër SystemV. Megjithatë, kur ka një numër të madh nyjesh, ardhja e një pakete të re TCP në një proces dhe marrja e të dhënave në radhë në një tjetër përfaqësojnë dy ngjarje konkurruese për OS. Në këtë rast, nëse nuk ka procesorë fizikë të disponueshëm për të dyja detyrat, njëri do të përpunohet dhe i dyti do të vendoset në një radhë pritjeje. Është e pamundur të parashikohen pasojat.

Në situata të tilla, mund të përdoret kontrolli dinamik i prioritetit të procesit, por kjo do të kërkojë përdorimin e thirrjeve të sistemit me burime intensive. Si rezultat, ne kaluam në një thread duke përdorur epoll klasik, kjo rriti shumë shpejtësinë dhe uli kohën e përpunimit të transaksionit. Ne gjithashtu hoqëm qafe proceset e veçanta të komunikimit në rrjet dhe komunikimin përmes SystemV, ulëm ndjeshëm numrin e thirrjeve të sistemit dhe filluam të kontrollojmë përparësitë e operacioneve. Vetëm në nënsistemin I/O, ishte e mundur të kurseheshin rreth 8-17 mikrosekonda, në varësi të skenarit. Kjo skemë me një fije është përdorur e pandryshuar që atëherë; mjafton një fije epoll me një diferencë për të shërbyer të gjitha lidhjet.

Përpunimi i transaksioneve

Ngarkesa në rritje në sistemin tonë kërkonte përmirësimin e pothuajse të gjithë komponentëve të tij. Por, për fat të keq, stanjacioni në rritjen e shpejtësisë së orës së procesorit në vitet e fundit nuk ka bërë më të mundur shkallëzimin e proceseve kokë më kokë. Prandaj, ne vendosëm ta ndajmë procesin e Motorit në tre nivele, ku më i ngarkuari prej tyre është sistemi i kontrollit të rrezikut, i cili vlerëson disponueshmërinë e fondeve në llogari dhe krijon vetë transaksionet. Por paratë mund të jenë në monedha të ndryshme, dhe ishte e nevojshme të kuptohej se mbi çfarë baze duhet të ndahej përpunimi i kërkesave.

Zgjidhja logjike është ta ndajmë atë sipas monedhës: një server tregton në dollarë, një tjetër në paund dhe një i tretë në euro. Por nëse, me një skemë të tillë, dërgohen dy transaksione për të blerë monedha të ndryshme, atëherë do të lindë problemi i desinkronizimit të portofolit. Por sinkronizimi është i vështirë dhe i shtrenjtë. Prandaj, do të ishte e saktë të copëtohej veçmas nga kuletat dhe veçmas sipas instrumenteve. Meqë ra fjala, shumica e shkëmbimeve perëndimore nuk kanë për detyrë të kontrollojnë rreziqet aq akute sa ne, kështu që më shpesh kjo bëhet jashtë linje. Na duhej të zbatonim verifikimin në internet.

Le të shpjegojmë me një shembull. Një tregtar dëshiron të blejë 30 dollarë dhe kërkesa shkon në vërtetimin e transaksionit: ne kontrollojmë nëse ky tregtar lejohet në këtë mënyrë tregtimi dhe nëse ai ka të drejtat e nevojshme. Nëse gjithçka është në rregull, kërkesa shkon në sistemin e verifikimit të rrezikut, d.m.th. për të kontrolluar mjaftueshmërinë e fondeve për të përfunduar një transaksion. Ekziston një shënim që shuma e kërkuar aktualisht është e bllokuar. Më pas, kërkesa i përcillet sistemit të tregtimit, i cili miraton ose kundërshton transaksionin. Le të themi se transaksioni është miratuar - atëherë sistemi i verifikimit të rrezikut shënon që paratë janë zhbllokuar dhe rubla kthehen në dollarë.

Në përgjithësi, sistemi i kontrollit të rrezikut përmban algoritme komplekse dhe kryen një sasi të madhe llogaritjesh me shumë burime intensive dhe nuk kontrollon thjesht "balancën e llogarisë", siç mund të duket në shikim të parë.

Kur filluam të ndajmë procesin e Motorit në nivele, hasëm një problem: kodi që ishte i disponueshëm në atë kohë përdorte në mënyrë aktive të njëjtin grup të dhënash në fazat e vërtetimit dhe verifikimit, gjë që kërkonte rishkrimin e të gjithë bazës së kodit. Si rezultat, ne huazuam një teknikë për përpunimin e udhëzimeve nga përpunuesit modernë: secila prej tyre ndahet në faza të vogla dhe disa veprime kryhen paralelisht në një cikël.

Evolucioni i arkitekturës së sistemit të tregtimit dhe pastrimit të Bursës së Moskës. Pjesa 2

Pas një përshtatjeje të vogël të kodit, ne krijuam një tubacion për përpunimin paralel të transaksioneve, në të cilin transaksioni u nda në 4 faza të tubacionit: ndërveprimi i rrjetit, vlefshmëria, ekzekutimi dhe publikimi i rezultatit.

Evolucioni i arkitekturës së sistemit të tregtimit dhe pastrimit të Bursës së Moskës. Pjesa 2

Le të shohim një shembull. Kemi dy sisteme përpunimi, serial dhe paralel. Transaksioni i parë mbërrin dhe dërgohet për vërtetim në të dy sistemet. Transaksioni i dytë arrin menjëherë: në një sistem paralel ai merret menjëherë në punë dhe në një sistem sekuencial vendoset në një radhë duke pritur që transaksioni i parë të kalojë në fazën aktuale të përpunimit. Kjo do të thotë, avantazhi kryesor i përpunimit të tubacionit është se ne përpunojmë radhën e transaksionit më shpejt.

Kështu dolëm me sistemin ASTS+.

Vërtetë, jo gjithçka është aq e qetë as me transportues. Le të themi se kemi një transaksion që ndikon në grupet e të dhënave në një transaksion fqinj; kjo është një situatë tipike për një shkëmbim. Një transaksion i tillë nuk mund të ekzekutohet në një tubacion sepse mund të prekë të tjerët. Kjo situatë quhet rrezik i të dhënave, dhe transaksione të tilla thjesht përpunohen veçmas: kur transaksionet "të shpejta" në radhë mbarojnë, tubacioni ndalon, sistemi përpunon transaksionin "i ngadalshëm" dhe më pas fillon përsëri tubacionin. Për fat të mirë, përqindja e transaksioneve të tilla në rrjedhën e përgjithshme është shumë e vogël, kështu që tubacioni ndalon aq rrallë sa nuk ndikon në performancën e përgjithshme.

Evolucioni i arkitekturës së sistemit të tregtimit dhe pastrimit të Bursës së Moskës. Pjesa 2

Pastaj filluam të zgjidhim problemin e sinkronizimit të tre fijeve të ekzekutimit. Rezultati ishte një sistem i bazuar në një tampon unazor me qeliza me madhësi fikse. Në këtë sistem, gjithçka i nënshtrohet shpejtësisë së përpunimit; të dhënat nuk kopjohen.

  • Të gjitha paketat hyrëse të rrjetit hyjnë në fazën e alokimit.
  • I vendosim në një grup dhe i shënojmë si të disponueshme për fazën #1.
  • Transaksioni i dytë ka mbërritur, është sërish i disponueshëm për fazën nr. 1.
  • Filli i parë i përpunimit sheh transaksionet e disponueshme, i përpunon ato dhe i zhvendos në fazën tjetër të fillit të dytë të përpunimit.
  • Më pas përpunon transaksionin e parë dhe shënon qelizën përkatëse deleted — tani është në dispozicion për përdorim të ri.

E gjithë radha përpunohet në këtë mënyrë.

Evolucioni i arkitekturës së sistemit të tregtimit dhe pastrimit të Bursës së Moskës. Pjesa 2

Përpunimi i çdo faze kërkon njësi ose dhjetëra mikrosekonda. Dhe nëse përdorim skemat standarde të sinkronizimit të sistemit operativ, do të humbasim më shumë kohë në vetë sinkronizimin. Kjo është arsyeja pse ne filluam të përdorim spinlock. Sidoqoftë, kjo është një formë shumë e keqe në një sistem në kohë reale dhe RedHat rreptësisht nuk rekomandon ta bëni këtë, kështu që ne aplikojmë një spinlock për 100 ms, dhe më pas kalojmë në modalitetin semafor për të eliminuar mundësinë e një bllokimi.

Si rezultat, ne arritëm një performancë prej rreth 8 milionë transaksionesh në sekondë. Dhe fjalë për fjalë dy muaj më vonë në artikull rreth LMAX Disruptor ne pamë një përshkrim të një qarku me të njëjtin funksionalitet.

Evolucioni i arkitekturës së sistemit të tregtimit dhe pastrimit të Bursës së Moskës. Pjesa 2

Tani mund të ketë disa fije ekzekutimi në një fazë. Të gjitha transaksionet u përpunuan një nga një, sipas renditjes së tyre. Si rezultat, performanca maksimale u rrit nga 18 mijë në 50 mijë transaksione në sekondë.

Sistemi i menaxhimit të rrezikut të këmbimit

Nuk ka kufi për përsosmërinë dhe së shpejti filluam përsëri modernizimin: në kuadër të ASTS+, filluam të zhvendosim sistemet e menaxhimit të rrezikut dhe operacioneve të shlyerjes në komponentë autonome. Ne zhvilluam një arkitekturë moderne fleksibël dhe një model të ri rreziku hierarkik dhe u përpoqëm ta përdorim klasën kudo që të ishte e mundur fixed_point në vend të double.

Por menjëherë u shfaq një problem: si të sinkronizoni të gjithë logjikën e biznesit që ka funksionuar për shumë vite dhe ta transferoni atë në sistemin e ri? Si rezultat, versioni i parë i prototipit të sistemit të ri duhej të braktisej. Versioni i dytë, i cili aktualisht është duke punuar në prodhim, bazohet në të njëjtin kod, i cili funksionon si në pjesën e tregtimit ashtu edhe në atë të rrezikut. Gjatë zhvillimit, gjëja më e vështirë për të bërë ishte bashkimi i git midis dy versioneve. Kolegu ynë Evgeniy Mazurenok e kryente këtë operacion çdo javë dhe çdo herë shante për një kohë shumë të gjatë.

Kur zgjidhnim një sistem të ri, menjëherë duhej të zgjidhnim problemin e ndërveprimit. Kur zgjidhni një autobus të dhënash, ishte e nevojshme të sigurohet nervozizëm i qëndrueshëm dhe vonesë minimale. Rrjeti InfiniBand RDMA ishte më i përshtatshmi për këtë: koha mesatare e përpunimit është 4 herë më pak se në rrjetet 10 G Ethernet. Por ajo që na mahniti me të vërtetë ishte ndryshimi në përqindje - 99 dhe 99,9.

Sigurisht, InfiniBand ka sfidat e veta. Së pari, një API tjetër - folje në vend të prizave. Së dyti, nuk ka pothuajse asnjë zgjidhje gjerësisht të disponueshme për mesazhe me burim të hapur. Ne u përpoqëm të bënim prototipin tonë, por doli të ishte shumë e vështirë, kështu që zgjodhëm një zgjidhje komerciale - Mesazhimi me vonesë të ulët të kufizuar (dikur IBM MQ LLM).

Pastaj lindi detyra e ndarjes së duhur të sistemit të rrezikut. Nëse thjesht hiqni Risk Engine dhe nuk krijoni një nyje të ndërmjetme, atëherë transaksionet nga dy burime mund të përzihen.

Evolucioni i arkitekturës së sistemit të tregtimit dhe pastrimit të Bursës së Moskës. Pjesa 2

Të ashtuquajturat zgjidhje të vonesës ultra të ulët kanë një mënyrë rirenditjeje: transaksionet nga dy burime mund të organizohen në rendin e kërkuar pas marrjes; kjo zbatohet duke përdorur një kanal të veçantë për shkëmbimin e informacionit rreth porosisë. Por ne nuk e përdorim ende këtë mënyrë: e ndërlikon të gjithë procesin dhe në një numër zgjidhjesh nuk mbështetet fare. Për më tepër, çdo transaksioni duhet t'i caktohen vulat kohore përkatëse dhe në skemën tonë ky mekanizëm është shumë i vështirë për t'u zbatuar saktë. Prandaj, ne përdorëm skemën klasike me një ndërmjetës mesazhesh, domethënë me një dispeçer që shpërndan mesazhe midis Risk Engine.

Problemi i dytë lidhej me aksesin e klientit: nëse ka disa Porta Rreziku, klienti duhet të lidhet me secilën prej tyre dhe kjo do të kërkojë ndryshime në shtresën e klientit. Ne donim të largoheshim nga kjo në këtë fazë, kështu që dizajni aktual i Portës së Rrezikut përpunon të gjithë rrjedhën e të dhënave. Kjo kufizon shumë xhiron maksimale, por thjeshton shumë integrimin e sistemit.

Dublikimi

Sistemi ynë nuk duhet të ketë një pikë të vetme dështimi, domethënë, të gjithë komponentët duhet të dublikohen, përfshirë ndërmjetësin e mesazheve. Ne e zgjidhëm këtë problem duke përdorur sistemin CLLM: ai përmban një grup RCMS në të cilin dy dispeçer mund të punojnë në modalitetin master-slave, dhe kur njëri dështon, sistemi kalon automatikisht në tjetrin.

Puna me një qendër të dhënash rezervë

InfiniBand është optimizuar për funksionimin si një rrjet lokal, domethënë për lidhjen e pajisjeve të montimit në raft dhe një rrjet InfiniBand nuk mund të vendoset midis dy qendrave të të dhënave të shpërndara gjeografikisht. Prandaj, ne kemi implementuar një urë/dispeçer, i cili lidhet me ruajtjen e mesazheve përmes rrjeteve të rregullta Ethernet dhe transmeton të gjitha transaksionet në një rrjet të dytë IB. Kur na duhet të migrojmë nga një qendër të dhënash, ne mund të zgjedhim me cilën qendër të dhënash të punojmë tani.

Rezultatet e

Të gjitha sa më sipër nuk u bënë menjëherë; u deshën disa përsëritje për zhvillimin e një arkitekture të re. Prototipin e krijuam brenda një muaji, por u deshën më shumë se dy vjet për ta vënë atë në gjendje pune. Ne u përpoqëm të arrinim kompromisin më të mirë midis rritjes së kohës së përpunimit të transaksioneve dhe rritjes së besueshmërisë së sistemit.

Meqenëse sistemi u përditësua shumë, ne zbatuam rikuperimin e të dhënave nga dy burime të pavarura. Nëse dyqani i mesazheve nuk funksionon siç duhet për ndonjë arsye, mund të merrni regjistrin e transaksioneve nga një burim i dytë - nga Risk Engine. Ky parim respektohet në të gjithë sistemin.

Ndër të tjera, ne ishim në gjendje të ruanim API-në e klientit në mënyrë që as ndërmjetësit dhe as dikush tjetër të mos kërkonin ripunim të rëndësishëm për arkitekturën e re. Na u desh të ndryshonim disa ndërfaqe, por nuk kishte nevojë të bënim ndryshime të rëndësishme në modelin e funksionimit.

Ne e quajtëm versionin aktual të platformës sonë Rebus - si një shkurtim për dy risitë më të dukshme në arkitekturë, Risk Engine dhe BUS.

Evolucioni i arkitekturës së sistemit të tregtimit dhe pastrimit të Bursës së Moskës. Pjesa 2

Fillimisht, ne donim të ndanim vetëm pjesën e pastrimit, por rezultati ishte një sistem i madh i shpërndarë. Klientët tani mund të ndërveprojnë me Trade Gateway, Clearing Gateway ose të dyja.

Çfarë arritëm në fund:

Evolucioni i arkitekturës së sistemit të tregtimit dhe pastrimit të Bursës së Moskës. Pjesa 2

Ulur nivelin e vonesës. Me një vëllim të vogël transaksionesh, sistemi funksionon njësoj si versioni i mëparshëm, por në të njëjtën kohë mund të përballojë një ngarkesë shumë më të lartë.

Performanca maksimale u rrit nga 50 mijë në 180 mijë transaksione në sekondë. Një rritje e mëtejshme pengohet nga rrjedha e vetme e përputhjes së rendit.

Ka dy mënyra për përmirësim të mëtejshëm: paralelizimi i përputhjes dhe ndryshimi i mënyrës se si funksionon me Gateway. Tani të gjitha Gateways funksionojnë sipas një skeme replikimi, e cila, nën një ngarkesë të tillë, pushon së funksionuari normalisht.

Së fundi, unë mund të jap disa këshilla për ata që janë duke finalizuar sistemet e ndërmarrjeve:

  • Jini të përgatitur për më të keqen në çdo kohë. Problemet lindin gjithmonë në mënyrë të papritur.
  • Zakonisht është e pamundur të ribëhet shpejt arkitektura. Sidomos nëse keni nevojë të arrini besueshmërinë maksimale në shumë tregues. Sa më shumë nyje, aq më shumë burime nevojiten për mbështetje.
  • Të gjitha zgjidhjet me porosi dhe të pronarit do të kërkojnë burime shtesë për kërkime, mbështetje dhe mirëmbajtje.
  • Mos e shtyni zgjidhjen e çështjeve të besueshmërisë dhe rikuperimit të sistemit pas dështimeve; merrni parasysh ato në fazën fillestare të projektimit.

Burimi: www.habr.com

Shto një koment