Kuriant patikimą, labai prieinamą, keičiamo dydžio paskirstytą sistemą, reikia laikytis konkrečių metodų, principų ir modelių. Kuriant tokias sistemas reikia spręsti daugybę iššūkių. Viena iš labiausiai paplitusių ir pagrindinių problemų yra dvigubo rašymo problema .
„Dvigubo rašymo problema“ yra iššūkis, kylantis paskirstytose sistemose, daugiausia dirbant su keliais duomenų šaltiniais arba duomenų bazėmis, kurias reikia sinchronizuoti. Tai reiškia, kad sunku užtikrinti, kad duomenų pakeitimai būtų nuosekliai įrašomi į įvairias duomenų saugyklas, pvz., duomenų bazes ar talpyklas, nesukeliant tokių problemų kaip duomenų neatitikimai, konfliktai ar našumo kliūtys.
Mikropaslaugų architektūra ir šablonų duomenų bazė kiekvienai paslaugai suteikia daug privalumų, tokių kaip nepriklausomas diegimas ir mastelio keitimas, atskiri gedimai ir galimas plėtros greičio padidėjimas. Tačiau norint atlikti operacijas, reikia keisti kelias mikropaslaugas, todėl reikia galvoti apie patikimą šios problemos sprendimą.
Panagrinėkime scenarijų, pagal kurį mūsų domenas apima paskolos paraiškų priėmimą, jų įvertinimą ir įspėjimų siuntimą klientams.
Vadovaujantis vienos atsakomybės principu, Conway dėsniu ir domenu pagrįsto dizaino metodu, po kelių įvykių audros seansų visas domenas buvo padalytas į tris subdomenus su apibrėžtais ribotais kontekstais, turinčiais aiškias ribas, domeno modelius ir visur esančią kalbą.
Pirmajai pavesta parengti ir sudaryti naujas paskolos paraiškas. Antroji sistema įvertina šias paraiškas ir pagal pateiktus duomenis priima sprendimus. Šis vertinimo procesas, įskaitant KYC / KYB, kovos su sukčiavimu ir kredito rizikos patikrinimus, gali užtrukti daug laiko, todėl reikia turėti galimybę vienu metu tvarkyti tūkstančius prašymų. Todėl ši funkcija buvo deleguota tam skirtai mikro paslaugai su savo duomenų baze, leidžiančia nepriklausomai keisti mastelį.
Be to, šias posistemes valdo dvi skirtingos komandos, kurių kiekviena turi savo išleidimo ciklus, paslaugų lygio sutartis (SLA) ir mastelio keitimo reikalavimus.
Galiausiai , yra sukurta specializuota pranešimų paslauga, skirta klientams siųsti įspėjimus.
Čia pateikiamas patobulintas pirminio sistemos naudojimo atvejo aprašymas:
Tai iš pirmo žvilgsnio gana paprasta ir primityvi sistema, tačiau pasinerkime į tai, kaip paskolos paraiškos paslauga apdoroja paskolos paraiškos pateikimo komandą.
Galime apsvarstyti du paslaugų sąveikos būdus:
Pirmiausia vietinis įsipareigojimas, tada paskelbimas: taikant šį metodą, paslauga atnaujina savo vietinę duomenų bazę (įsipareigoja) ir tada paskelbia įvykį arba pranešimą kitoms paslaugoms.
Pirmiausia paskelbkite, tada vietinis patvirtinimas: ir atvirkščiai, šis metodas apima įvykio arba pranešimo paskelbimą prieš atliekant pakeitimus vietinėje duomenų bazėje.
Abu metodai turi savo trūkumų ir yra tik iš dalies saugūs ryšiui paskirstytose sistemose.
Tai yra pirmojo metodo taikymo sekos diagrama.
Pagal šį scenarijų paskolos paraiškos paslauga naudoja metodą „Pirmiausia vietinis įsipareigojimas, tada paskelbk“ , kai pirmiausia atlieka operaciją, o tada bando išsiųsti pranešimą kitai sistemai. Tačiau šis procesas gali sugesti, jei, pavyzdžiui, yra tinklo problemų, vertinimo paslauga nepasiekiama arba paskolos paraiškos tarnyba aptinka atminties trūkumo (OOM) klaidą ir sugenda. Tokiais atvejais pranešimas būtų prarastas, o Vertinimas liktų nepranešęs apie naują paskolos paraišką, nebent būtų įgyvendintos papildomos priemonės.
Ir antrasis.
Pagal scenarijų „Pirmą kartą paskelbkite, tada vietinį įsipareigojimą“ paskolos paraiškos paslauga susiduria su didesne rizika. Jis gali informuoti vertinimo tarnybą apie naują programą, bet nepavyks išsaugoti šio naujinimo vietoje dėl problemų, pvz., duomenų bazės problemų, atminties klaidų ar kodo klaidų. Šis metodas gali sukelti didelių duomenų neatitikimų, o tai gali sukelti rimtų problemų, atsižvelgiant į tai, kaip paskolų peržiūros tarnyba tvarko gaunamas paraiškas.
Todėl turime nustatyti sprendimą, kuris pasiūlytų patikimą įvykių paskelbimo išoriniams vartotojams mechanizmą. Tačiau prieš gilindamiesi į galimus sprendimus, pirmiausia turėtume išsiaiškinti pranešimų pristatymo garantijų tipus, pasiekiamus paskirstytose sistemose.
Galime pasiekti keturių tipų garantijas.
Jokių garantijų
Nėra garantijos, kad pranešimas bus pristatytas į paskirties vietą. „First-Local-Commit-Then-Publish“ metodas yra būtent apie tai. Vartotojai gali gauti pranešimus vieną kartą, kelis kartus arba iš viso negauti.
Daugiausiai vieną kartą pristatymas
Ne daugiau kaip vieną kartą pristatymas reiškia, kad pranešimas bus pristatytas į paskirties vietą daugiausia 1 kartą. Metodas „Pirmiausia vietinis, įpareigoti, tada paskelbti“ gali būti įgyvendintas tokiu būdu, taip pat naudojant bandymų pakartotinio bandymo politiką su viena verte.
Bent kartą pristatymas\Vartotojai gaus ir apdoros kiekvieną pranešimą, tačiau tą patį pranešimą gali gauti daugiau nei vieną kartą.
Tiksliai vieną kartą pristatymas\Tiksliai vieną kartą pristatymas reiškia, kad vartotojas pranešimą gaus veiksmingai vieną kartą.
Techniškai tai įmanoma pasiekti su Kafka sandoriais ir specifiniu idempotentu gamintojo ir vartotojo įgyvendinimu.
Daugeliu atvejų „bent kartą“ pristatymo garantija išsprendžia daugelį problemų, nes užtikrina, kad pranešimai būtų pristatyti bent vieną kartą, tačiau vartotojai turi būti bejėgiai. Tačiau, atsižvelgiant į neišvengiamus tinklo gedimus, visa vartotojų logika turi būti nepastebima, kad būtų išvengta pasikartojančių pranešimų apdorojimo, nepaisant gamintojo garantijų. Todėl šis reikalavimas yra ne tiek trūkumas, kiek jis atspindi tikrovę.
Yra daugybė šios problemos sprendimų, kurie turi savo privalumų ir trūkumų.
Anot Vikipedijos, „Two-Phase Commit“ (2PC) yra paskirstytas transakcijų protokolas, naudojamas kompiuterių moksle ir duomenų bazių valdymo sistemose, siekiant užtikrinti paskirstytų operacijų nuoseklumą ir patikimumą. Jis skirtas situacijoms, kai vienoje operacijoje turi dalyvauti keli ištekliai (pvz., duomenų bazės), ir užtikrina, kad visi jie atliks operaciją arba visi ją nutrauks, taip išlaikant duomenų nuoseklumą. Skamba būtent tai, ko mums reikia, tačiau dviejų fazių įsipareigojimas turi keletą trūkumų:
Akivaizdžiausias sprendimas mikropaslaugų architektūrai yra taikyti šabloną (ar net kartais antipatterną) – bendrinamą duomenų bazę. Šis metodas yra labai intuityvus, jei reikia operacijų nuoseklumo keliose lentelėse skirtingose duomenų bazėse, tiesiog naudokite vieną bendrinamą duomenų bazę šioms mikropaslaugoms.
Šio metodo trūkumai apima vieno gedimo taško įvedimą, nepriklausomo duomenų bazės mastelio keitimo slopinimą ir galimybės naudoti skirtingus duomenų bazių sprendimus, geriausiai tinkančius konkretiems reikalavimams ir naudojimo atvejams, ribojimą. Be to, norint palaikyti tokią paskirstytų operacijų formą, reikėtų keisti mikropaslaugų kodų bazes.
„ Operacijų siuntimo dėžutė “ yra dizaino modelis, naudojamas paskirstytose sistemose, siekiant užtikrinti patikimą pranešimų sklaidą, net ir esant nepatikimoms pranešimų sistemoms. Tai apima įvykių saugojimą nurodytoje „OutboxEvents“ lentelėje toje pačioje operacijoje kaip ir pati operacija. Šis metodas gerai suderinamas su reliacinių duomenų bazių ACID savybėmis. Priešingai, daugelis No-SQL duomenų bazių nevisiškai palaiko ACID ypatybes, o vietoj to pasirenka BŽŪP teoremos ir BASE filosofijos principus, kurie teikia pirmenybę prieinamumui ir galutiniam nuoseklumui, o ne griežtam nuoseklumui.
Operacijų siuntimo dėžutė suteikia bent vieną garantiją ir gali būti įgyvendinta keliais būdais:
Sandorių žurnalo uodega
Apklausos leidėjas
Operacijų žurnalo uodegos sudarymo metodas reiškia duomenų bazei būdingų sprendimų, tokių kaip CDC (Change Data Capture), naudojimą. Pagrindiniai šio metodo trūkumai yra šie:
Duomenų bazės specifiniai sprendimai
Padidėjęs delsos laikas dėl CDC diegimo specifikos
Kitas būdas yra Polling Publisher , kuris palengvina siunčiamų laiškų iškrovimą, apklausdamas išsiuntimo lentelę. Pagrindinis šio metodo trūkumas yra galimybė padidinti duomenų bazių apkrovą, dėl kurios gali padidėti išlaidos. Be to, ne visos No-SQL duomenų bazės palaiko veiksmingą užklausą dėl konkrečių dokumentų segmentų. Todėl ištraukus visus dokumentus gali pablogėti veikimas.
Čia yra nedidelė sekos diagrama, paaiškinanti, kaip tai veikia.
Pagrindinis iššūkis, susijęs su Transactional Outbox modeliu, yra jo priklausomybė nuo duomenų bazės ACID savybių. Tai gali būti paprasta įprastose OLTP duomenų bazėse, bet kelia iššūkių NoSQL srityje. Norint tai išspręsti, galimas sprendimas yra panaudoti pridėjimo žurnalą (pvz., Kafka) nuo pat užklausos apdorojimo inicijavimo.
Užuot tiesiogiai apdoroję komandą „Pateikti paskolos paraišką“, nedelsdami išsiunčiame ją į vidinę „Kafka“ temą ir grąžiname klientui „priimtą“ rezultatą. Tačiau, kadangi labai tikėtina, kad komandą dar reikės apdoroti, negalime iš karto informuoti kliento apie rezultatą. Norėdami valdyti šį galimą nuoseklumą, galime naudoti tokius metodus kaip ilga apklausa, kliento inicijuota apklausa, optimistiški vartotojo sąsajos naujinimai arba naudojant žiniatinklio lizdus arba serverio išsiųstus įvykius pranešimams. Tačiau tai visiškai atskira tema, todėl grįžkime prie pradinės temos.
Išsiuntėme pranešimą vidine Kafkos tema. Paskolos prašymo tarnyba sunaudoja šį pranešimą – tą pačią komandą, kurią gavo iš kliento – ir pradeda apdoroti. Pirma, ji vykdo tam tikrą verslo logiką; tik sėkmingai įgyvendinus šią logiką ir išlaikius rezultatus, ji skelbia naujus pranešimus vieša Kafkos tema.
Pažvelkime į pseudokodą.
public async Task HandleAsync(SubmitLoanApplicationCommand command, ...) { //First, process business logic var loanApplication = await _loanApplicationService.HandleCommandAsync(command, ...); //Then, send new events to public Kafka topic producer.Send(new LoanApplicationSubmittedEvent(loanApplication.Id)); //Then, commit offset consumer.Commit(); }
Ką daryti, jei verslo logikos apdorojimas nepavyks? Nesijaudinkite, kadangi įskaitymas dar nebuvo atliktas, pranešimas bus bandomas dar kartą.
Ką daryti, jei naujų įvykių siuntimas Kafkai nepavyks? Nesijaudinkite, nes verslo logika yra bejėgė, todėl paskolos paraiškos dublikatas nebus sukurtas. Vietoj to jis bandys iš naujo siųsti pranešimus viešai Kafkos temai.
Ką daryti, jei pranešimai siunčiami Kafkai, bet kompensuoti nepavyksta? Nesijaudinkite, nes verslo logika yra bejėgė, todėl paskolos paraiškos dublikatas nebus sukurtas. Vietoj to, jis iš naujo siųs pranešimus viešai Kafkos temai ir tikisi, kad šį kartą kompensacinis įsipareigojimas pavyks.
Pagrindiniai šio metodo trūkumai apima papildomą sudėtingumą, susijusį su nauju programavimo stiliumi, galimą nuoseklumą (nes klientas iš karto nesužinos rezultato) ir reikalavimą, kad visa verslo logika būtų ideali.
Kas yra renginių tiekimas ir kaip jį būtų galima pritaikyti čia? Įvykių šaltinis yra programinės įrangos architektūrinis modelis, naudojamas modeliuoti sistemos būseną, fiksuojant visus jos duomenų pakeitimus kaip nekintamų įvykių seriją. Šie įvykiai atspindi faktus arba būsenos pokyčius ir yra vienintelis tiesos šaltinis dabartinei sistemos būsenai. Taigi, techniškai, įdiegę įvykių šaltinio sistemą, mes jau turime visus įvykius EventStore, o šią EventStore vartotojai gali naudoti kaip vieną tiesos apie tai, kas nutiko, šaltinį. Nereikia konkretaus duomenų bazės sprendimo, kad būtų galima sekti visus pakeitimus ar susirūpinimą dėl užsakymo, vienintelė problema yra sėdėti skaitymo pusėje, nes norint gauti faktinę objekto būseną, reikia pakartoti visus įvykius.
Šiame straipsnyje apžvelgėme kelis patikimo pranešimų siuntimo paskirstytose sistemose kūrimo metodus. Yra keletas rekomendacijų, į kurias galėtume atsižvelgti kurdami sistemas su šiomis savybėmis
Kitą kartą pažvelgsime į praktiškesnį operacijų siuntimo dėžutės diegimo pavyzdį. Žr
tu!