paint-brush
Mesazhe të besueshme në Sistemet e Shpërndaranga@fairday
37,190 lexime
37,190 lexime

Mesazhe të besueshme në Sistemet e Shpërndara

nga Aleksei8m2024/03/18
Read on Terminal Reader
Read this story w/o Javascript

Shume gjate; Te lexosh

Ndërtimi i një sistemi të shpërndarë të besueshëm, shumë të disponueshëm, të shkallëzuar kërkon respektimin e teknikave, parimeve dhe modeleve specifike.
featured image - Mesazhe të besueshme në Sistemet e Shpërndara
Aleksei HackerNoon profile picture

Problem me shkrim të dyfishtë

Ndërtimi i një sistemi të shpërndarë të besueshëm, shumë të disponueshëm, të shkallëzuar kërkon respektimin e teknikave, parimeve dhe modeleve specifike. Dizajni i sistemeve të tilla përfshin adresimin e një morie sfidash. Ndër çështjet më të përhapura dhe themelore është problemi i shkrimit të dyfishtë .


"Problemi i shkrimit të dyfishtë" është një sfidë që lind në sistemet e shpërndara, kryesisht kur kemi të bëjmë me burime të shumta të të dhënave ose baza të të dhënave që duhet të mbahen të sinkronizuara. Ai i referohet vështirësisë për të siguruar që ndryshimet e të dhënave të shkruhen në mënyrë të vazhdueshme në dyqane të ndryshme të të dhënave, të tilla si bazat e të dhënave ose cache, pa paraqitur çështje si mospërputhjet e të dhënave, konfliktet ose pengesat e performancës.


Arkitektura e mikroshërbimeve dhe baza e të dhënave të modeleve për shërbim ju sjell shumë përfitime, të tilla si vendosja dhe shkallëzimi i pavarur, dështimet e izoluara dhe një rritje e mundshme e shpejtësisë së zhvillimit. Megjithatë, operacionet kërkojnë ndryshime midis mikroshërbimeve të shumta, duke ju detyruar të mendoni për një zgjidhje të besueshme për të trajtuar këtë problem.

Pothuajse një shembull i vërtetë

Le të shqyrtojmë një skenar në të cilin domeni ynë përfshin pranimin e aplikacioneve për kredi, vlerësimin e tyre dhe më pas dërgimin e njoftimeve për klientët.


Në frymën e parimit të përgjegjësisë së vetme, ligjit të Conway dhe qasjes së dizajnit të drejtuar nga domeni, pas disa sesioneve të stuhisë së ngjarjeve, i gjithë domeni u nda në tre nënfusha me kontekste të kufizuara të përcaktuara që kishin kufij të qartë, modele domenesh dhe gjuhë të kudondodhur.


E para ka për detyrë të përfshijë dhe përpilojë aplikacione të reja për kredi. Sistemi i dytë vlerëson këto aplikacione dhe merr vendime bazuar në të dhënat e ofruara. Ky proces vlerësimi, duke përfshirë kontrollet KYC/KYB, kundër mashtrimit dhe rrezikut të kredisë, mund të marrë kohë, duke kërkuar aftësinë për të trajtuar mijëra aplikacione njëkohësisht. Rrjedhimisht, ky funksion i është deleguar një mikroshërbimi të dedikuar me bazën e të dhënave të tij, duke lejuar shkallëzim të pavarur.

Për më tepër, këto nënsisteme menaxhohen nga dy ekipe të ndryshme, secila me ciklet e veta të lëshimit, marrëveshjet e nivelit të shërbimit (SLA) dhe kërkesat e shkallëzueshmërisë.


Së fundi , është krijuar një shërbim i specializuar njoftimi për të dërguar sinjalizime te klientët.



Këtu është një përshkrim i rafinuar i rastit të përdorimit parësor të sistemit:

  1. Një klient paraqet një kërkesë për kredi.
  2. Shërbimi i Aplikimit për Kredi regjistron aplikimin e ri me statusin "Presht" dhe nis procesin e vlerësimit duke ia përcjellë aplikacionin Shërbimit të Vlerësimit.
  3. Shërbimi i Vlerësimit vlerëson kërkesën e ardhur për kredi dhe më pas informon Shërbimin e Aplikimit për Kredi për vendimin.
  4. Me marrjen e vendimit, Shërbimi i Aplikimit për Kredi përditëson statusin e aplikimit për kredi në përputhje me rrethanat dhe aktivizon Shërbimin e Njoftimeve për të informuar klientin për rezultatin.
  5. Shërbimi i Njoftimeve e përpunon këtë kërkesë dhe i dërgon njoftimet klientit nëpërmjet postës elektronike, SMS ose metodave të tjera të preferuara të komunikimit, sipas cilësimeve të klientit.


Është një sistem mjaft i thjeshtë dhe primitiv në shikim të parë, por le të zhytemi në mënyrën se si shërbimi i aplikimit për kredi e përpunon komandën e dorëzimit të aplikimit për kredi.


Ne mund të konsiderojmë dy qasje për ndërveprimet e shërbimit:

  1. First-Local-Commit-Then-Publish: Në këtë qasje, shërbimi përditëson bazën e të dhënave të tij lokale (kommitimet) dhe më pas publikon një ngjarje ose mesazh për shërbime të tjera.

  2. First-Publish-Then-Local-Commit: Anasjelltas, kjo metodë përfshin publikimin e një ngjarjeje ose mesazhi përpara se të kryeni ndryshimet në bazën e të dhënave lokale.


Të dyja metodat kanë të metat e tyre dhe janë vetëm pjesërisht të sigurta për dështimin për komunikim në sistemet e shpërndara.


Ky është një diagram i sekuencës së aplikimit të qasjes së parë.


Së pari-Local-Commit-Pastaj-Publiko


Në këtë skenar, Shërbimi i Aplikimit të Huasë përdor qasjen First-Local-Commit-Then-Publish , ku fillimisht kryen një transaksion dhe më pas tenton të dërgojë një njoftim në një sistem tjetër. Megjithatë, ky proces është i ndjeshëm ndaj dështimit nëse, për shembull, ka probleme me rrjetin, Shërbimi i Vlerësimit nuk është i disponueshëm ose Shërbimi i Aplikimit të Huasë ndeshet me një gabim jashtë memorie (OOM) dhe prishet. Në raste të tilla, mesazhi do të humbiste, duke lënë Vlerësimin pa njoftim për aplikimin e ri të kredisë, përveç nëse zbatohen masa shtesë.


Dhe e dyta.

First-Publish-Past-Local-Commit
Në skenarin First-Publish-Pan-Local-Commit , Shërbimi i Aplikimit për Kredi përballet me rreziqe më të rëndësishme. Mund të informojë Shërbimin e Vlerësimit për një aplikacion të ri, por nuk mund ta ruajë këtë përditësim në nivel lokal për shkak të problemeve si problemet e bazës së të dhënave, gabimet e kujtesës ose defektet e kodit. Kjo qasje mund të çojë në mospërputhje të konsiderueshme në të dhëna, të cilat mund të shkaktojnë probleme serioze, në varësi të mënyrës se si Shërbimi i Rishikimit të Huasë trajton aplikacionet hyrëse.


Prandaj, ne duhet të identifikojmë një zgjidhje që ofron një mekanizëm të fuqishëm për publikimin e ngjarjeve për konsumatorët e jashtëm. Por, përpara se të thellohemi në zgjidhjet e mundshme, së pari duhet të sqarojmë llojet e garancive të dërgimit të mesazheve që mund të arrihen në sistemet e shpërndara.

Garancitë për dërgimin e mesazheve

Ka katër lloje garancish që mund të arrijmë.

  1. Asnjë garanci
    Nuk ka asnjë garanci që mesazhi do të dërgohet në destinacion. Qasja First-Local-Commit-Pas-Publish ka të bëjë pikërisht me këtë. Konsumatorët mund të marrin mesazhe një herë, disa herë ose kurrë.

  2. Dorëzimi maksimumi një herë
    Dorëzimi maksimumi një herë do të thotë që mesazhi do të dërgohet në destinacion maksimumi 1 herë. Qasja First-Local-Commit-Then-Publish mund të zbatohet në këtë mënyrë gjithashtu me politikën e riprovës së përpjekjeve me vlerën një.

  3. Të paktën një herë dërgesa\Konsumatorët do të marrin dhe përpunojnë çdo mesazh, por mund të marrin të njëjtin mesazh më shumë se një herë.

  4. Pikërisht një herë dërgesë\Saktësisht një herë dërgesë do të thotë që konsumatori do ta marrë mesazhin në mënyrë efektive një herë.
    Teknikisht, është e mundur të arrihen me Kafka transaksionet dhe zbatimin specifik idempotent të prodhuesit dhe konsumatorit.


Në shumicën e rasteve, garancitë e dorëzimit 'të paktën një herë' trajtojnë shumë çështje duke siguruar që mesazhet të dërgohen të paktën një herë, por konsumatorët duhet të jenë të pafuqishëm. Megjithatë, duke pasur parasysh dështimet e pashmangshme të rrjetit, e gjithë logjika e konsumatorit duhet të jetë e pafuqishme për të shmangur përpunimin e mesazheve të dyfishta, pavarësisht nga garancitë e prodhuesit. Prandaj, kjo kërkesë nuk është aq shumë pengesë sa pasqyron realitetin.

Zgjidhjet

Ka shumë zgjidhje për këtë problem, të cilat kanë avantazhet dhe disavantazhet e tyre.

Komiteti dyfazor

Sipas Wikipedia, Komiteti Dyfazor (2PC) është një protokoll transaksioni i shpërndarë i përdorur në shkencën kompjuterike dhe sistemet e menaxhimit të bazës së të dhënave për të siguruar qëndrueshmërinë dhe besueshmërinë e transaksioneve të shpërndara. Është projektuar për situata ku burime të shumta (p.sh., bazat e të dhënave) duhet të marrin pjesë në një transaksion të vetëm, dhe siguron që ose të gjithë ta kryejnë transaksionin ose të gjithë ta ndërpresin atë, duke ruajtur kështu konsistencën e të dhënave. Duket pikërisht ajo që na nevojitet, por Komiteti Dyfazor ka disa të meta:

  • Nëse një burim pjesëmarrës nuk reagon ose përjeton një dështim, i gjithë procesi mund të bllokohet derisa problemi të zgjidhet. Kjo mund të çojë në probleme të mundshme të performancës dhe disponueshmërisë.
  • Komiteti dyfazor nuk ofron mekanizma të integruar të tolerancës së gabimeve. Ai mbështetet në mekanizma të jashtëm ose ndërhyrje manuale për të trajtuar dështimet.
  • Jo të gjitha bazat e të dhënave moderne mbështesin Commit Dy Fazor.

Baza e të dhënave e përbashkët

Zgjidhja më e dukshme për arkitekturën e mikroshërbimeve është aplikimi i një modeli (ose ndonjëherë edhe anti-model) - një bazë të dhënash të përbashkët. Kjo qasje është shumë intuitive nëse keni nevojë për konsistencë transaksionesh nëpër tabela të shumta në baza të të dhënave të ndryshme, thjesht përdorni një bazë të dhënash të përbashkët për këto mikroshërbime.


Disavantazhet e kësaj qasjeje përfshijnë futjen e një pike të vetme dështimi, frenimin e shkallëzimit të pavarur të bazës së të dhënave dhe kufizimin e aftësisë për të përdorur zgjidhje të ndryshme të bazës së të dhënave më të përshtatshme për kërkesat specifike dhe rastet e përdorimit. Për më tepër, modifikimet në bazat e kodeve të mikroshërbimeve do të ishin të nevojshme për të mbështetur një formë të tillë të transaksionit të shpërndarë.

Kutia dalëse e transaksioneve

' Kutia e transaksionit ' është një model projektimi i përdorur në sistemet e shpërndara për të siguruar përhapje të besueshme të mesazheve, edhe përballë sistemeve të mesazheve jo të besueshme. Ai përfshin ruajtjen e ngjarjeve në një tabelë të caktuar 'OutboxEvents' brenda të njëjtit transaksion si vetë operacioni. Kjo qasje përputhet mirë me vetitë ACID të bazave të të dhënave relacionale. Në të kundërt, shumë baza të të dhënave No-SQL nuk mbështesin plotësisht vetitë ACID, duke zgjedhur në vend të kësaj për parimet e teoremës CAP dhe filozofisë BASE, të cilat i japin përparësi disponueshmërisë dhe qëndrueshmërisë eventuale mbi qëndrueshmërinë strikte.


Një kuti dalëse transaksionale ofron të paktën një garanci dhe mund të zbatohet me disa qasje:

  1. Përfundimi i regjistrit të transaksioneve

  2. Botuesi i sondazhit


Qasja e pakësimit të regjistrit të transaksioneve nënkupton përdorimin e zgjidhjeve specifike të bazës së të dhënave si CDC (Change Data Capture). Disavantazhet kryesore të kësaj qasjeje janë:

  • Zgjidhje specifike të bazës së të dhënave

  • Rritja e vonesës për shkak të specifikave të zbatimeve të CDC


Një metodë tjetër është Polling Publisher , i cili lehtëson shkarkimin e kutisë dalëse duke votuar tabelën e kutisë dalëse. E meta kryesore e kësaj qasjeje është potenciali për rritjen e ngarkesës së bazës së të dhënave, e cila mund të çojë në kosto më të larta. Për më tepër, jo të gjitha bazat e të dhënave No-SQL mbështesin kërkimin efikas për segmente të veçanta dokumentesh. Prandaj, nxjerrja e dokumenteve të tëra mund të rezultojë në degradim të performancës.


Këtu është një diagram i vogël sekuence që shpjegon se si funksionon.


Dëgjoje veten

Sfida kryesore me modelin Transactional Outbox qëndron në varësinë e tij nga vetitë ACID të bazës së të dhënave. Mund të jetë e drejtpërdrejtë në bazat e të dhënave tipike OLTP, por paraqet sfida në fushën NoSQL. Për të adresuar këtë, një zgjidhje e mundshme është përdorimi i regjistrit të shtojcave (për shembull, Kafka) që nga fillimi i përpunimit të kërkesës.


Në vend që të përpunojmë drejtpërdrejt komandën 'dorëzoni kërkesën për kredi', ne e dërgojmë atë menjëherë në një temë të brendshme të Kafkës dhe më pas i kthejmë klientit një rezultat 'të pranuar'. Megjithatë, meqenëse ka shumë të ngjarë që komanda duhet ende të përpunohet, ne nuk mund ta informojmë menjëherë klientin për rezultatin. Për të menaxhuar këtë qëndrueshmëri eventuale, ne mund të përdorim teknika të tilla si sondazhi i gjatë, sondazhi i inicuar nga klienti, përditësimet optimiste të ndërfaqes së përdoruesit, ose përdorimi i WebSockets ose Ngjarjet e dërguara nga serveri për njoftime. Megjithatë, kjo është një temë krejtësisht e veçantë, kështu që le të kthehemi në temën tonë fillestare.


Ne e dërguam mesazhin për një temë të brendshme të Kafkës. Shërbimi i Aplikimit për Kredi më pas konsumon këtë mesazh - të njëjtën komandë që ka marrë nga klienti - dhe fillon përpunimin. Së pari, ai ekzekuton disa logjikë biznesi; vetëm pasi kjo logjikë të jetë ekzekutuar me sukses dhe rezultatet të vazhdojnë, ai publikon mesazhe të reja për një temë publike të Kafkës.


Le t'i hedhim një vështrim pak pseudo-kodit.


 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(); }


Po nëse përpunimi i logjikës së biznesit dështon? Mos u shqetësoni, pasi kompensimi nuk është kryer ende, mesazhi do të riprovohet.


Po nëse dërgimi i ngjarjeve të reja te Kafka dështon? Mos u shqetësoni, pasi logjika e biznesit është idempotente, nuk do të krijojë një aplikim kredie të dyfishtë. Në vend të kësaj, do të përpiqet të ridërgojë mesazhe në temën publike të Kafkës.


Po sikur mesazhet t'i dërgohen Kafkës, por kryerja e kompensimit dështon? Mos u shqetësoni, meqenëse logjika e biznesit është e pafuqishme, nuk do të krijojë një aplikim të dyfishtë për kredi. Në vend të kësaj, do të ridërgojë mesazhe në temën publike të Kafkës dhe do të shpresojë që angazhimi i kompensimit të ketë sukses këtë herë.


Disavantazhet kryesore të kësaj qasjeje përfshijnë kompleksitetin e shtuar të lidhur me një stil të ri programimi, qëndrueshmërinë eventuale (pasi klienti nuk do ta dijë menjëherë rezultatin) dhe kërkesën që e gjithë logjika e biznesit të jetë idempotente.

Burimi i ngjarjeve

Çfarë është burimi i ngjarjeve dhe si mund të zbatohet këtu? Burimi i ngjarjeve është një model arkitektonik softuerësh i përdorur për të modeluar gjendjen e një sistemi duke kapur të gjitha ndryshimet në të dhënat e tij si një seri ngjarjesh të pandryshueshme. Këto ngjarje përfaqësojnë fakte ose tranzicione shtetërore dhe shërbejnë si burimi i vetëm i së vërtetës për gjendjen aktuale të sistemit. Pra, teknikisht, duke zbatuar një sistem të burimit të ngjarjeve, ne tashmë i kemi të gjitha ngjarjet në EventStore dhe ky EventStore mund të përdoret nga konsumatorët si një burim i vetëm i së vërtetës për atë që ka ndodhur. Nuk ka nevojë për një zgjidhje specifike të bazës së të dhënave për ndjekjen e të gjitha ndryshimeve ose shqetësimeve në lidhje me porositjen, problemi i vetëm është të qëndrosh në anën e lexuar pasi që të jesh në gjendje të marrësh gjendjen aktuale të entitetit kërkohet të riprodhohen të gjitha ngjarjet.

konkluzioni

Në këtë artikull, ne shqyrtuam disa qasje për ndërtimin e mesazheve të besueshme në sistemet e shpërndara. Ka disa rekomandime që mund të marrim parasysh gjatë ndërtimit të sistemeve me këto karakteristika

  1. Gjithmonë zhvilloni konsumatorë të pafuqishëm pasi dështimi i rrjetit është i pashmangshëm.
  2. Përdorni me kujdes First-Local-Commit-Then-Publish me një kuptim të qartë të kërkesave të garancisë.
  3. Asnjëherë mos përdorni qasjen First-Publish-Then Local-Commit pasi kjo mund të çojë në mospërputhje të rënda të të dhënave në sistemin tuaj.
  4. Nëse vendimi për zgjedhjen e bazës së të dhënave ekzistuese ka shumë të ngjarë të ndryshojë ose strategjia teknike nënkupton zgjedhjen e zgjidhjes më të mirë të ruajtjes për problemin - mos ndërtoni biblioteka të përbashkëta duke u lidhur me zgjidhjet e bazës së të dhënave si CDC .
  5. Përdorni qasjen Transactional Outbox si një zgjidhje standarde për të arritur të paktën një herë garanci.
  6. Merrni parasysh përdorimin e qasjes Listen to veten kur përdoren bazat e të dhënave No-SQL.


Herën tjetër, do të shikojmë një shembull më praktik të zbatimit të një kutie dalëse transaksioni. Shihni

ju!