Հուսալի, մատչելի, լայնածավալ բաշխված համակարգ կառուցելը պահանջում է հատուկ տեխնիկայի, սկզբունքների և օրինաչափությունների պահպանում: Նման համակարգերի նախագծումը ներառում է մի շարք մարտահրավերների լուծում: Ամենատարածված և հիմնարար խնդիրներից է երկակի գրելու խնդիրը :
«Երկակի գրելու խնդիրը» մարտահրավեր է, որն առաջանում է բաշխված համակարգերում, հիմնականում, երբ գործ ունենք բազմաթիվ տվյալների աղբյուրների կամ տվյալների բազաների հետ, որոնք պետք է համաժամեցվեն: Դա վերաբերում է դժվարությանն ապահովելու, որ տվյալների փոփոխությունները հետևողականորեն գրվեն տվյալների տարբեր պահեստներում, ինչպիսիք են տվյալների բազաները կամ քեշերը, առանց այնպիսի խնդիրների, ինչպիսիք են տվյալների անհամապատասխանությունը, կոնֆլիկտները կամ կատարողականի խցանումները:
Միկրոծառայությունների ճարտարապետությունը և օրինաչափությունների տվյալների բազան յուրաքանչյուր ծառայության համար բերում են ձեզ բազմաթիվ առավելություններ, ինչպիսիք են անկախ տեղակայումը և մասշտաբը, մեկուսացված ձախողումները և զարգացման արագության հնարավոր խթանումը: Այնուամենայնիվ, գործողությունները պահանջում են փոփոխություններ բազմաթիվ միկրոծառայությունների միջև, ինչը ձեզ ստիպում է մտածել այս խնդիրը լուծելու հուսալի լուծման մասին:
Եկեք դիտարկենք մի սցենար, որի դեպքում մեր տիրույթը ներառում է վարկի հայտերի ընդունում, դրանց գնահատում, այնուհետև հաճախորդներին ծանուցումների ծանուցումներ ուղարկելը:
Միասնական պատասխանատվության սկզբունքի, Conway-ի օրենքի և տիրույթի վրա հիմնված նախագծման մոտեցման ոգով, մի քանի իրադարձությունների փոթորիկ նիստերից հետո ամբողջ տիրույթը բաժանվեց երեք ենթադոմեյնների՝ սահմանված սահմանափակ համատեքստերով, որոնք ունեն հստակ սահմաններ, տիրույթի մոդելներ և ամենուր տարածված լեզու:
Առաջինին հանձնարարված է մուտքագրել և կազմել նոր վարկային հայտեր: Երկրորդ համակարգը գնահատում է այս հավելվածները և որոշումներ կայացնում՝ հիմնվելով ներկայացված տվյալների վրա: Գնահատման այս գործընթացը, ներառյալ KYC/KYB, խարդախության դեմ և վարկային ռիսկի ստուգումները, կարող են ժամանակատար լինել, ինչը պահանջում է միաժամանակ հազարավոր դիմումներ մշակելու ունակություն: Հետևաբար, այս ֆունկցիոնալությունը փոխանցվել է հատուկ միկրոսերվիսին, որն ունի իր տվյալների բազան, որը թույլ է տալիս անկախ մասշտաբավորում:
Ավելին, այս ենթահամակարգերը կառավարվում են երկու տարբեր թիմերի կողմից, որոնցից յուրաքանչյուրն ունի իր թողարկման ցիկլերը, ծառայության մակարդակի համաձայնագրերը (SLA) և մասշտաբայնության պահանջները:
Ի վերջո , գործում է ծանուցման մասնագիտացված ծառայություն՝ հաճախորդներին ծանուցումներ ուղարկելու համար:
Ահա համակարգի առաջնային օգտագործման դեպքի հստակեցված նկարագրությունը.
Սա բավականին պարզ և պարզունակ համակարգ է առաջին հայացքից, բայց եկեք խորանանք, թե ինչպես է Վարկի դիմումի ծառայությունը մշակում վարկի դիմում ներկայացնելու հրամանը:
Ծառայությունների փոխազդեցության համար մենք կարող ենք դիտարկել երկու մոտեցում.
First-Local-Commit-Then-Publish. Այս մոտեցմամբ ծառայությունը թարմացնում է իր տեղական տվյալների բազան (կոմիտացիաներ) և այնուհետև հրապարակում իրադարձություն կամ հաղորդագրություն այլ ծառայությունների համար:
First-Publish-Then-Local-Commit. Ընդհակառակը, այս մեթոդը ներառում է իրադարձություն կամ հաղորդագրություն հրապարակել նախքան տեղական տվյալների բազայում փոփոխություններ կատարելը:
Երկու մեթոդներն էլ ունեն իրենց թերությունները և մասնակիորեն անվտանգ են բաշխված համակարգերում հաղորդակցության համար:
Սա առաջին մոտեցման կիրառման հաջորդական դիագրամ է:
Այս սցենարում Վարկի Դիմումի Ծառայությունն օգտագործում է First-Local-Commit-Then-Publish մոտեցումը, որտեղ նախ կատարում է գործարք, այնուհետև փորձում է ծանուցում ուղարկել մեկ այլ համակարգ: Այնուամենայնիվ, այս գործընթացը ենթակա է ձախողման, եթե, օրինակ, կան ցանցային խնդիրներ, Գնահատման ծառայությունն անհասանելի է, կամ Վարկի Դիմումի Ծառայությունը բախվում է հիշողությունից դուրս (OOM) սխալի և խափանում է: Նման դեպքերում հաղորդագրությունը կկորչի՝ թողնելով Գնահատումը առանց նոր վարկի դիմումի մասին ծանուցման, եթե լրացուցիչ միջոցներ չկիրառվեն:
Եվ երկրորդը.
First-Publish-Then-Local-Commit սցենարի դեպքում Վարկի Դիմումի Ծառայությունը բախվում է ավելի նշանակալի ռիսկերի: Այն կարող է տեղեկացնել Գնահատման ծառայությանը նոր հավելվածի մասին, սակայն չի հաջողվի պահպանել այս թարմացումը տեղում՝ տվյալների բազայի խնդիրների, հիշողության սխալների կամ կոդի սխալների պատճառով: Այս մոտեցումը կարող է հանգեցնել տվյալների զգալի անհամապատասխանության, ինչը կարող է լուրջ խնդիրներ առաջացնել՝ կախված այն բանից, թե ինչպես է Վարկի վերանայման ծառայությունը մշակում մուտքային դիմումները:
Հետևաբար, մենք պետք է բացահայտենք լուծում, որն առաջարկում է արտաքին սպառողներին իրադարձությունների հրապարակման ամուր մեխանիզմ: Բայց, նախքան հնարավոր լուծումների մեջ խորանալը, մենք նախ պետք է հստակեցնենք բաշխված համակարգերում հասանելի հաղորդագրությունների առաքման երաշխիքների տեսակները:
Կան չորս տեսակի երաշխիքներ, որոնց մենք կարող ենք հասնել:
Ոչ մի երաշխիք
Ոչ մի երաշխիք չկա, որ հաղորդագրությունը կհասցվի նպատակակետին: First-Local-Commit-Then-Publish մոտեցումը հենց այս մասին է: Սպառողները կարող են հաղորդագրություններ ստանալ մեկ անգամ, մի քանի անգամ կամ ընդհանրապես երբեք:
Առավելագույնը մեկ անգամ առաքում
Առավելագույնը մեկ անգամ առաքումը նշանակում է, որ հաղորդագրությունը կհասցվի նպատակակետ առավելագույնը 1 անգամ: First-Local-Commit-Then-Publish մոտեցումը կարող է իրականացվել այս կերպ ևս մեկ արժեքով փորձերի կրկնակի քաղաքականության միջոցով:
Առնվազն մեկ անգամ առաքում\Սպառողները կստանան և կմշակեն յուրաքանչյուր հաղորդագրություն, բայց կարող են ստանալ նույն հաղորդագրությունը մեկից ավելի անգամ:
Հենց մեկ անգամ առաքում\Հենց մեկ անգամ առաքում նշանակում է, որ սպառողը մեկ անգամ արդյունավետ կերպով կստանա հաղորդագրությունը:
Տեխնիկապես դա հնարավոր է հասնել Կաֆկայի գործարքների և արտադրողի և սպառողի կոնկրետ անիմաստ իրականացման միջոցով:
Շատ դեպքերում «առնվազն մեկ անգամ» առաքման երաշխիքները լուծում են բազմաթիվ խնդիրներ՝ ապահովելով հաղորդագրությունների առաքումը առնվազն մեկ անգամ, սակայն սպառողները պետք է անզոր լինեն: Այնուամենայնիվ, հաշվի առնելով ցանցի անխուսափելի խափանումները, սպառողի ողջ տրամաբանությունը պետք է լինի անզոր՝ խուսափելու կրկնօրինակ հաղորդագրությունների մշակումից՝ անկախ արտադրողի երաշխիքներից: Հետևաբար, այս պահանջը ոչ այնքան թերություն է, որքան այն արտացոլում է իրականությունը:
Այս խնդրի լուծման բազմաթիվ տարբերակներ կան, որոնք ունեն իրենց առավելություններն ու թերությունները:
Ըստ Վիքիպեդիայի՝ երկփուլային պարտավորությունը (2PC) բաշխված գործարքի արձանագրություն է, որն օգտագործվում է համակարգչային գիտության և տվյալների բազայի կառավարման համակարգերում՝ ապահովելու բաշխված գործարքների հետևողականությունն ու հուսալիությունը։ Այն նախատեսված է այնպիսի իրավիճակների համար, երբ մի քանի ռեսուրսներ (օրինակ՝ տվյալների բազաներ) պետք է մասնակցեն մեկ գործարքին, և այն ապահովում է, որ կամ բոլորը կկատարեն գործարքը, կամ բոլորը դադարեցնեն այն՝ դրանով իսկ պահպանելով տվյալների հետևողականությունը: Դա հնչում է հենց այն, ինչ մեզ անհրաժեշտ է, բայց երկու փուլային կատարումն ունի մի քանի թերություններ.
Միկրոծառայությունների ճարտարապետության ամենաակնհայտ լուծումը օրինաչափություն (կամ նույնիսկ երբեմն հակապատկեր) կիրառելն է՝ ընդհանուր տվյալների բազա: Այս մոտեցումը շատ ինտուիտիվ է, եթե ձեզ անհրաժեշտ է գործարքների հետևողականություն մի քանի աղյուսակների միջև տարբեր տվյալների բազաներում, պարզապես օգտագործեք մեկ ընդհանուր տվյալների բազա այս միկրոծառայությունների համար:
Այս մոտեցման թերությունները ներառում են ձախողման մեկ կետի ներդրումը, տվյալների բազայի անկախ մասշտաբի արգելումը և տվյալների բազայի տարբեր լուծումների օգտագործման հնարավորությունը սահմանափակելը, որոնք լավագույնս համապատասխանում են հատուկ պահանջներին և օգտագործման դեպքերին: Բացի այդ, միկրոծառայությունների կոդերի բազայի փոփոխությունները անհրաժեշտ կլինեն բաշխված գործարքի նման ձևին աջակցելու համար:
« Գործարքային ելքային արկղը » դիզայնի օրինաչափություն է, որն օգտագործվում է բաշխված համակարգերում՝ ապահովելու հուսալի հաղորդագրությունների տարածում, նույնիսկ անհուսալի հաղորդագրությունների համակարգերի դեպքում: Այն ներառում է իրադարձությունների պահպանում նշանակված «OutboxEvents» աղյուսակում նույն գործարքի շրջանակներում, ինչ գործողությունը: Այս մոտեցումը լավ համընկնում է հարաբերական տվյալների բազաների ACID հատկությունների հետ: Ի հակադրություն, շատ No-SQL տվյալների բազաներ լիովին չեն աջակցում ACID հատկություններին, փոխարենը ընտրելով CAP թեորեմի և BASE փիլիսոփայության սկզբունքները, որոնք առաջնահերթություն են տալիս հասանելիությանը և վերջնական հետևողականությանը խիստ հետևողականությունից:
Գործարքի ելքային արկղը տրամադրում է առնվազն մեկ անգամ երաշխիք և կարող է իրականացվել մի քանի մոտեցումներով.
Գործարքների տեղեկամատյանների պոչամբար
Հարցումների հրատարակիչ
Գործարքների մատյանների պոչամբարի մոտեցումը ենթադրում է տվյալների բազայի հատուկ լուծումների օգտագործում, ինչպիսին է 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-ը կարող է օգտագործվել սպառողների կողմից որպես կատարվածի վերաբերյալ ճշմարտության միակ աղբյուր: Բոլոր փոփոխություններին կամ պատվիրման հետ կապված մտահոգություններին հետևելու համար տվյալների բազայի հատուկ լուծման կարիք չկա, միակ խնդիրը կարդալու կողմում մնալն է, քանի որ իրական վիճակի հասնելու համար պահանջվում է վերարտադրել բոլոր իրադարձությունները:
Այս հոդվածում մենք վերանայեցինք բաշխված համակարգերում հուսալի հաղորդագրություններ ստեղծելու մի քանի մոտեցումներ: Կան մի քանի առաջարկներ, որոնք մենք կարող ենք հաշվի առնել այս բնութագրերով համակարգեր կառուցելիս
Հաջորդ անգամ մենք կանդրադառնանք Գործարքի ելքային արկղի ներդրման ավելի գործնական օրինակին: Տես
դու!