paint-brush
Հուսալի հաղորդագրություններ բաշխված համակարգերումկողմից@fairday
37,380 ընթերցումներ
37,380 ընթերցումներ

Հուսալի հաղորդագրություններ բաշխված համակարգերում

կողմից Aleksei8m2024/03/18
Read on Terminal Reader
Read this story w/o Javascript

Չափազանց երկար; Կարդալ

Հուսալի, մատչելի, լայնածավալ բաշխված համակարգ կառուցելը պահանջում է հատուկ տեխնիկայի, սկզբունքների և օրինաչափությունների պահպանում:
featured image - Հուսալի հաղորդագրություններ բաշխված համակարգերում
Aleksei HackerNoon profile picture

Կրկնակի գրելու խնդիր

Հուսալի, մատչելի, լայնածավալ բաշխված համակարգ կառուցելը պահանջում է հատուկ տեխնիկայի, սկզբունքների և օրինաչափությունների պահպանում: Նման համակարգերի նախագծումը ներառում է մի շարք մարտահրավերների լուծում: Ամենատարածված և հիմնարար խնդիրներից է երկակի գրելու խնդիրը :


«Երկակի գրելու խնդիրը» մարտահրավեր է, որն առաջանում է բաշխված համակարգերում, հիմնականում, երբ գործ ունենք բազմաթիվ տվյալների աղբյուրների կամ տվյալների բազաների հետ, որոնք պետք է համաժամեցվեն: Դա վերաբերում է դժվարությանն ապահովելու, որ տվյալների փոփոխությունները հետևողականորեն գրվեն տվյալների տարբեր պահեստներում, ինչպիսիք են տվյալների բազաները կամ քեշերը, առանց այնպիսի խնդիրների, ինչպիսիք են տվյալների անհամապատասխանությունը, կոնֆլիկտները կամ կատարողականի խցանումները:


Միկրոծառայությունների ճարտարապետությունը և օրինաչափությունների տվյալների բազան յուրաքանչյուր ծառայության համար բերում են ձեզ բազմաթիվ առավելություններ, ինչպիսիք են անկախ տեղակայումը և մասշտաբը, մեկուսացված ձախողումները և զարգացման արագության հնարավոր խթանումը: Այնուամենայնիվ, գործողությունները պահանջում են փոփոխություններ բազմաթիվ միկրոծառայությունների միջև, ինչը ձեզ ստիպում է մտածել այս խնդիրը լուծելու հուսալի լուծման մասին:

Գրեթե իրական օրինակ

Եկեք դիտարկենք մի սցենար, որի դեպքում մեր տիրույթը ներառում է վարկի հայտերի ընդունում, դրանց գնահատում, այնուհետև հաճախորդներին ծանուցումների ծանուցումներ ուղարկելը:


Միասնական պատասխանատվության սկզբունքի, Conway-ի օրենքի և տիրույթի վրա հիմնված նախագծման մոտեցման ոգով, մի քանի իրադարձությունների փոթորիկ նիստերից հետո ամբողջ տիրույթը բաժանվեց երեք ենթադոմեյնների՝ սահմանված սահմանափակ համատեքստերով, որոնք ունեն հստակ սահմաններ, տիրույթի մոդելներ և ամենուր տարածված լեզու:


Առաջինին հանձնարարված է մուտքագրել և կազմել նոր վարկային հայտեր: Երկրորդ համակարգը գնահատում է այս հավելվածները և որոշումներ կայացնում՝ հիմնվելով ներկայացված տվյալների վրա: Գնահատման այս գործընթացը, ներառյալ KYC/KYB, խարդախության դեմ և վարկային ռիսկի ստուգումները, կարող են ժամանակատար լինել, ինչը պահանջում է միաժամանակ հազարավոր դիմումներ մշակելու ունակություն: Հետևաբար, այս ֆունկցիոնալությունը փոխանցվել է հատուկ միկրոսերվիսին, որն ունի իր տվյալների բազան, որը թույլ է տալիս անկախ մասշտաբավորում:

Ավելին, այս ենթահամակարգերը կառավարվում են երկու տարբեր թիմերի կողմից, որոնցից յուրաքանչյուրն ունի իր թողարկման ցիկլերը, ծառայության մակարդակի համաձայնագրերը (SLA) և մասշտաբայնության պահանջները:


Ի վերջո , գործում է ծանուցման մասնագիտացված ծառայություն՝ հաճախորդներին ծանուցումներ ուղարկելու համար:



Ահա համակարգի առաջնային օգտագործման դեպքի հստակեցված նկարագրությունը.

  1. Հաճախորդը վարկի դիմում է ներկայացնում:
  2. Վարկային հայտի ծառայությունը գրանցում է նոր հայտը «Սպասող» կարգավիճակով և նախաձեռնում է գնահատման գործընթացը՝ հայտը Գնահատման ծառայություն փոխանցելով:
  3. Գնահատման ծառայությունը գնահատում է մուտքային վարկային հայտը և հետագայում որոշման մասին տեղեկացնում Վարկային հայտի ծառայությանը:
  4. Որոշումը ստանալուց հետո Վարկային հայտի ծառայությունը համապատասխանաբար թարմացնում է վարկի հայտի կարգավիճակը և գործարկում է Ծանուցումների ծառայությունը՝ հաճախորդին տեղեկացնելու արդյունքի մասին:
  5. Ծանուցումների ծառայությունը մշակում է այս հարցումը և հաճախորդին ուղարկում է ծանուցումներ էլ.


Սա բավականին պարզ և պարզունակ համակարգ է առաջին հայացքից, բայց եկեք խորանանք, թե ինչպես է Վարկի դիմումի ծառայությունը մշակում վարկի դիմում ներկայացնելու հրամանը:


Ծառայությունների փոխազդեցության համար մենք կարող ենք դիտարկել երկու մոտեցում.

  1. First-Local-Commit-Then-Publish. Այս մոտեցմամբ ծառայությունը թարմացնում է իր տեղական տվյալների բազան (կոմիտացիաներ) և այնուհետև հրապարակում իրադարձություն կամ հաղորդագրություն այլ ծառայությունների համար:

  2. First-Publish-Then-Local-Commit. Ընդհակառակը, այս մեթոդը ներառում է իրադարձություն կամ հաղորդագրություն հրապարակել նախքան տեղական տվյալների բազայում փոփոխություններ կատարելը:


Երկու մեթոդներն էլ ունեն իրենց թերությունները և մասնակիորեն անվտանգ են բաշխված համակարգերում հաղորդակցության համար:


Սա առաջին մոտեցման կիրառման հաջորդական դիագրամ է:


First-Local-Commit-Then-Publish


Այս սցենարում Վարկի Դիմումի Ծառայությունն օգտագործում է First-Local-Commit-Then-Publish մոտեցումը, որտեղ նախ կատարում է գործարք, այնուհետև փորձում է ծանուցում ուղարկել մեկ այլ համակարգ: Այնուամենայնիվ, այս գործընթացը ենթակա է ձախողման, եթե, օրինակ, կան ցանցային խնդիրներ, Գնահատման ծառայությունն անհասանելի է, կամ Վարկի Դիմումի Ծառայությունը բախվում է հիշողությունից դուրս (OOM) սխալի և խափանում է: Նման դեպքերում հաղորդագրությունը կկորչի՝ թողնելով Գնահատումը առանց նոր վարկի դիմումի մասին ծանուցման, եթե լրացուցիչ միջոցներ չկիրառվեն:


Եվ երկրորդը.

First-Publish-Then-Local-Commit
First-Publish-Then-Local-Commit սցենարի դեպքում Վարկի Դիմումի Ծառայությունը բախվում է ավելի նշանակալի ռիսկերի: Այն կարող է տեղեկացնել Գնահատման ծառայությանը նոր հավելվածի մասին, սակայն չի հաջողվի պահպանել այս թարմացումը տեղում՝ տվյալների բազայի խնդիրների, հիշողության սխալների կամ կոդի սխալների պատճառով: Այս մոտեցումը կարող է հանգեցնել տվյալների զգալի անհամապատասխանության, ինչը կարող է լուրջ խնդիրներ առաջացնել՝ կախված այն բանից, թե ինչպես է Վարկի վերանայման ծառայությունը մշակում մուտքային դիմումները:


Հետևաբար, մենք պետք է բացահայտենք լուծում, որն առաջարկում է արտաքին սպառողներին իրադարձությունների հրապարակման ամուր մեխանիզմ: Բայց, նախքան հնարավոր լուծումների մեջ խորանալը, մենք նախ պետք է հստակեցնենք բաշխված համակարգերում հասանելի հաղորդագրությունների առաքման երաշխիքների տեսակները:

Հաղորդագրությունների առաքման երաշխիքներ

Կան չորս տեսակի երաշխիքներ, որոնց մենք կարող ենք հասնել:

  1. Ոչ մի երաշխիք
    Ոչ մի երաշխիք չկա, որ հաղորդագրությունը կհասցվի նպատակակետին: First-Local-Commit-Then-Publish մոտեցումը հենց այս մասին է: Սպառողները կարող են հաղորդագրություններ ստանալ մեկ անգամ, մի քանի անգամ կամ ընդհանրապես երբեք:

  2. Առավելագույնը մեկ անգամ առաքում
    Առավելագույնը մեկ անգամ առաքումը նշանակում է, որ հաղորդագրությունը կհասցվի նպատակակետ առավելագույնը 1 անգամ: First-Local-Commit-Then-Publish մոտեցումը կարող է իրականացվել այս կերպ ևս մեկ արժեքով փորձերի կրկնակի քաղաքականության միջոցով:

  3. Առնվազն մեկ անգամ առաքում\Սպառողները կստանան և կմշակեն յուրաքանչյուր հաղորդագրություն, բայց կարող են ստանալ նույն հաղորդագրությունը մեկից ավելի անգամ:

  4. Հենց մեկ անգամ առաքում\Հենց մեկ անգամ առաքում նշանակում է, որ սպառողը մեկ անգամ արդյունավետ կերպով կստանա հաղորդագրությունը:
    Տեխնիկապես դա հնարավոր է հասնել Կաֆկայի գործարքների և արտադրողի և սպառողի կոնկրետ անիմաստ իրականացման միջոցով:


Շատ դեպքերում «առնվազն մեկ անգամ» առաքման երաշխիքները լուծում են բազմաթիվ խնդիրներ՝ ապահովելով հաղորդագրությունների առաքումը առնվազն մեկ անգամ, սակայն սպառողները պետք է անզոր լինեն: Այնուամենայնիվ, հաշվի առնելով ցանցի անխուսափելի խափանումները, սպառողի ողջ տրամաբանությունը պետք է լինի անզոր՝ խուսափելու կրկնօրինակ հաղորդագրությունների մշակումից՝ անկախ արտադրողի երաշխիքներից: Հետևաբար, այս պահանջը ոչ այնքան թերություն է, որքան այն արտացոլում է իրականությունը:

Լուծումներ

Այս խնդրի լուծման բազմաթիվ տարբերակներ կան, որոնք ունեն իրենց առավելություններն ու թերությունները:

Երկու փուլային պարտավորություն

Ըստ Վիքիպեդիայի՝ երկփուլային պարտավորությունը (2PC) բաշխված գործարքի արձանագրություն է, որն օգտագործվում է համակարգչային գիտության և տվյալների բազայի կառավարման համակարգերում՝ ապահովելու բաշխված գործարքների հետևողականությունն ու հուսալիությունը։ Այն նախատեսված է այնպիսի իրավիճակների համար, երբ մի քանի ռեսուրսներ (օրինակ՝ տվյալների բազաներ) պետք է մասնակցեն մեկ գործարքին, և այն ապահովում է, որ կամ բոլորը կկատարեն գործարքը, կամ բոլորը դադարեցնեն այն՝ դրանով իսկ պահպանելով տվյալների հետևողականությունը: Դա հնչում է հենց այն, ինչ մեզ անհրաժեշտ է, բայց երկու փուլային կատարումն ունի մի քանի թերություններ.

  • Եթե որևէ մասնակից ռեսուրս դառնում է անպատասխան կամ ձախողվում է, ամբողջ գործընթացը կարող է արգելափակվել մինչև խնդիրը լուծվի: Սա կարող է հանգեցնել աշխատանքի և հասանելիության հնարավոր խնդիրների:
  • Երկու փուլային կոմիտը չի ապահովում ներկառուցված սխալների հանդուրժողականության մեխանիզմներ: Այն հենվում է արտաքին մեխանիզմների կամ ձեռքի միջամտության վրա՝ խափանումները հաղթահարելու համար:
  • Ոչ բոլոր ժամանակակից տվյալների շտեմարաններն են աջակցում երկու փուլային կոմիտին:

Համօգտագործվող տվյալների բազա

Միկրոծառայությունների ճարտարապետության ամենաակնհայտ լուծումը օրինաչափություն (կամ նույնիսկ երբեմն հակապատկեր) կիրառելն է՝ ընդհանուր տվյալների բազա: Այս մոտեցումը շատ ինտուիտիվ է, եթե ձեզ անհրաժեշտ է գործարքների հետևողականություն մի քանի աղյուսակների միջև տարբեր տվյալների բազաներում, պարզապես օգտագործեք մեկ ընդհանուր տվյալների բազա այս միկրոծառայությունների համար:


Այս մոտեցման թերությունները ներառում են ձախողման մեկ կետի ներդրումը, տվյալների բազայի անկախ մասշտաբի արգելումը և տվյալների բազայի տարբեր լուծումների օգտագործման հնարավորությունը սահմանափակելը, որոնք լավագույնս համապատասխանում են հատուկ պահանջներին և օգտագործման դեպքերին: Բացի այդ, միկրոծառայությունների կոդերի բազայի փոփոխությունները անհրաժեշտ կլինեն բաշխված գործարքի նման ձևին աջակցելու համար:

Գործարքի ելքային արկղ

« Գործարքային ելքային արկղը » դիզայնի օրինաչափություն է, որն օգտագործվում է բաշխված համակարգերում՝ ապահովելու հուսալի հաղորդագրությունների տարածում, նույնիսկ անհուսալի հաղորդագրությունների համակարգերի դեպքում: Այն ներառում է իրադարձությունների պահպանում նշանակված «OutboxEvents» աղյուսակում նույն գործարքի շրջանակներում, ինչ գործողությունը: Այս մոտեցումը լավ համընկնում է հարաբերական տվյալների բազաների ACID հատկությունների հետ: Ի հակադրություն, շատ No-SQL տվյալների բազաներ լիովին չեն աջակցում ACID հատկություններին, փոխարենը ընտրելով CAP թեորեմի և BASE փիլիսոփայության սկզբունքները, որոնք առաջնահերթություն են տալիս հասանելիությանը և վերջնական հետևողականությանը խիստ հետևողականությունից:


Գործարքի ելքային արկղը տրամադրում է առնվազն մեկ անգամ երաշխիք և կարող է իրականացվել մի քանի մոտեցումներով.

  1. Գործարքների տեղեկամատյանների պոչամբար

  2. Հարցումների հրատարակիչ


Գործարքների մատյանների պոչամբարի մոտեցումը ենթադրում է տվյալների բազայի հատուկ լուծումների օգտագործում, ինչպիսին է CDC-ն (Փոխել տվյալների հավաքագրումը): Այդ մոտեցման հիմնական թերություններն են.

  • Տվյալների բազայի հատուկ լուծումներ

  • Աճող ուշացում՝ պայմանավորված CDC-ի ներդրման առանձնահատկություններով


Մեկ այլ մեթոդ Polling Publisher-ն է, որը հեշտացնում է ելքային արկղերի բեռնաթափումը` ելքային աղյուսակի հարցումների միջոցով: Այս մոտեցման հիմնական թերությունը տվյալների բազայի բեռնվածության ավելացման ներուժն է, որը կարող է հանգեցնել ավելի մեծ ծախսերի: Ավելին, ոչ բոլոր No-SQL տվյալների բազաները աջակցում են արդյունավետ հարցումներ կոնկրետ փաստաթղթերի հատվածների համար: Հետևաբար, ամբողջական փաստաթղթերի արդյունահանումը կարող է հանգեցնել արդյունավետության վատթարացման:


Ահա մի փոքր հաջորդական դիագրամ, որը բացատրում է, թե ինչպես է այն աշխատում:


Լսեք ինքներդ ձեզ

Գործարքների ելքային օրինաչափության հետ կապված առաջնային խնդիրը կայանում է նրանում, որ այն կախված է տվյալների բազայի ACID հատկություններից: Այն կարող է պարզ լինել բնորոշ OLTP տվյալների բազաներում, բայց մարտահրավերներ է ստեղծում NoSQL ոլորտում: Այս խնդրի լուծման համար հնարավոր լուծում է հավելվածի գրանցամատյանի օգտագործումը (օրինակ, Կաֆկա) անմիջապես հարցումների մշակումը սկսելուց:


Փոխանակ ուղղակիորեն մշակելու «ներկայացնել վարկի հայտ» հրամանը, մենք այն անմիջապես ուղարկում ենք Կաֆկայի ներքին թեմա և այնուհետև վերադարձնում «ընդունված» արդյունքը հաճախորդին: Այնուամենայնիվ, քանի որ շատ հավանական է, որ հրամանը դեռ պետք է մշակվի, մենք չենք կարող անմիջապես հաճախորդին տեղեկացնել արդյունքի մասին: Այս վերջնական հետևողականությունը կառավարելու համար մենք կարող ենք կիրառել այնպիսի մեթոդներ, ինչպիսիք են երկարատև հարցումը, հաճախորդի կողմից նախաձեռնված հարցումը, UI-ի լավատեսական թարմացումները կամ օգտագործելով WebSockets կամ Server-Sent Events ծանուցումների համար: Այնուամենայնիվ, սա ընդհանրապես առանձին թեմա է, ուստի վերադառնանք մեր սկզբնական թեմային:


Մենք հաղորդագրություն ենք ուղարկել Կաֆկայի ներքին թեմայով. Վարկի հայտի ծառայությունն այնուհետև օգտագործում է այս հաղորդագրությունը՝ նույն հրամանը, որը ստացել է հաճախորդից, և սկսում է մշակումը: Նախ, այն իրականացնում է որոշակի բիզնես տրամաբանություն. միայն այն բանից հետո, երբ այս տրամաբանությունը հաջողությամբ իրականացվի և արդյունքները պահպանվեն, այն հրապարակում է նոր հաղորդագրություններ հանրային Կաֆկայի թեմայով:


Եկեք մի փոքր նայենք կեղծ ծածկագրին:


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


Իսկ եթե բիզնես տրամաբանության մշակումը ձախողվի: Անհանգստացեք, քանի որ օֆսեթը դեռ չի կատարվել, հաղորդագրությունը նորից կփորձվի:


Իսկ եթե Կաֆկային նոր իրադարձություններ ուղարկելը ձախողվի: Մի անհանգստացեք, քանի որ բիզնեսի տրամաբանությունը անիմաստ է, այն չի ստեղծի կրկնօրինակ վարկի դիմում: Փոխարենը, այն կփորձի նորից հաղորդագրություններ ուղարկել Կաֆկայի հանրային թեմային:


Իսկ եթե հաղորդագրություններ ուղարկվեն Կաֆկային, բայց օֆսեթ հանձնումը ձախողվի: Մի անհանգստացեք, քանի որ բիզնեսի տրամաբանությունը անիմաստ է, այն չի ստեղծի կրկնօրինակ վարկի դիմում: Փոխարենը, այն նորից հաղորդագրություններ կուղարկի հանրային Կաֆկայի թեմային և հուսով է, որ օֆսեթ հանձնումն այս անգամ կհաջողվի:


Այս մոտեցման հիմնական թերությունները ներառում են ավելացված բարդությունը՝ կապված նոր ծրագրավորման ոճի հետ, վերջնական հետևողականությունը (քանի որ հաճախորդը անմիջապես չի իմանա արդյունքը) և ամբողջ բիզնես տրամաբանության անիմաստ լինելու պահանջը:

Միջոցառումների աղբյուր

Ի՞նչ է իրադարձությունների աղբյուրը և ինչպե՞ս կարող է այն կիրառվել այստեղ: Իրադարձությունների աղբյուրը ծրագրային ճարտարապետական օրինաչափություն է, որն օգտագործվում է համակարգի վիճակը մոդելավորելու համար՝ նրա տվյալների բոլոր փոփոխությունները որպես անփոփոխ իրադարձությունների շարք: Այս իրադարձությունները ներկայացնում են փաստեր կամ վիճակների անցումներ և ծառայում են որպես ճշմարտության միակ աղբյուր համակարգի ներկա վիճակի համար: Այսպիսով, տեխնիկապես, ներդնելով իրադարձությունների աղբյուրների համակարգ, մենք արդեն ունենք բոլոր իրադարձությունները EventStore-ում, և այս EventStore-ը կարող է օգտագործվել սպառողների կողմից որպես կատարվածի վերաբերյալ ճշմարտության միակ աղբյուր: Բոլոր փոփոխություններին կամ պատվիրման հետ կապված մտահոգություններին հետևելու համար տվյալների բազայի հատուկ լուծման կարիք չկա, միակ խնդիրը կարդալու կողմում մնալն է, քանի որ իրական վիճակի հասնելու համար պահանջվում է վերարտադրել բոլոր իրադարձությունները:

Եզրակացություն

Այս հոդվածում մենք վերանայեցինք բաշխված համակարգերում հուսալի հաղորդագրություններ ստեղծելու մի քանի մոտեցումներ: Կան մի քանի առաջարկներ, որոնք մենք կարող ենք հաշվի առնել այս բնութագրերով համակարգեր կառուցելիս

  1. Միշտ զարգացրեք անիմաստ սպառողներ, քանի որ ցանցի խափանումն անխուսափելի է:
  2. Զգուշորեն օգտագործեք First-Local-Commit-Then-Publish-ը՝ երաշխիքային պահանջների հստակ ըմբռնմամբ:
  3. Երբեք մի օգտագործեք First-Publish-Then-Local-Commit մոտեցումը, քանի որ դա կարող է հանգեցնել ձեր համակարգում տվյալների խիստ անհամապատասխանության:
  4. Եթե տվյալների բազայի ընտրության գոյություն ունեցող որոշումը, ամենայն հավանականությամբ, կարող է փոխվել, կամ տեխնիկական ռազմավարությունը ենթադրում է խնդրի պահպանման լավագույն լուծումը ընտրելը, մի՛ կառուցեք ընդհանուր գրադարաններ՝ միանալով տվյալների բազայի լուծումներին, ինչպիսին է CDC-ն :
  5. Օգտագործեք Գործարքների ելքային մոտեցումը որպես ստանդարտ լուծում՝ առնվազն մեկ անգամ երաշխիքներ ստանալու համար:
  6. Մտածեք Լսեք ինքներդ ձեզ մոտեցումը, երբ No-SQL տվյալների բազաները օգտագործվում են:


Հաջորդ անգամ մենք կանդրադառնանք Գործարքի ելքային արկղի ներդրման ավելի գործնական օրինակին: Տես

դու!