Изградња поузданог, високо доступног, скалабилног дистрибуираног система захтева придржавање специфичних техника, принципа и образаца. Дизајн таквих система укључује решавање безброј изазова. Међу најчешћим и најосновнијим проблемима је проблем двоструког писања .
„Проблем двоструког писања“ је изазов који се јавља у дистрибуираним системима, углавном када се ради са више извора података или база података које треба да буду синхронизоване. Односи се на потешкоће да се обезбеди да се промене података доследно уписују у различита складишта података, као што су базе података или кеш меморије, без увођења проблема као што су недоследности података, сукоби или уска грла у перформансама.
Архитектура микросервиса и база података образаца по услузи вам доносе многе предности, као што су независна примена и скалирање, изоловани кварови и потенцијално повећање брзине развоја. Међутим, операције захтевају промене међу више микроуслуга, што вас тера да размишљате о поузданом решењу за решавање овог проблема.
Хајде да размотримо сценарио у коме наш домен подразумева прихватање захтева за кредит, њихову процену, а затим слање обавештења клијентима.
У духу принципа јединствене одговорности, Конвејевог закона и приступа дизајна вођеног доменом, након неколико сесија које су се бавиле догађајима, цео домен је подељен на три поддомена са дефинисаним ограниченим контекстима који имају јасне границе, моделе домена и свеприсутни језик.
Први има задатак да прихвати и састави нове апликације за кредит. Други систем процењује ове апликације и доноси одлуке на основу достављених података. Овај процес процене, укључујући КИЦ/КИБ, провере против превара и кредитног ризика, може да потраје, што захтева могућност да се истовремено обрађује хиљаде апликација. Сходно томе, ова функционалност је делегирана наменском микросервису са сопственом базом података, омогућавајући независно скалирање.
Штавише, овим подсистемима управљају два различита тима, сваки са сопственим циклусима издавања, уговорима о нивоу услуге (СЛА) и захтевима за скалабилност.
На крају , постоји специјализована услуга обавештења за слање упозорења купцима.
Ево префињеног описа примарног случаја употребе система:
То је на први поглед прилично једноставан и примитиван систем, али хајде да заронимо у то како услуга апликације за зајам обрађује команду за подношење захтева за кредит.
Можемо размотрити два приступа за интеракције услуга:
Фирст-Лоцал-Цоммит-Тхен-Публисх: У овом приступу, услуга ажурира своју локалну базу података (урезује) и затим објављује догађај или поруку другим услугама.
Прво-објави-па-локално-урезивање: Насупрот томе, овај метод укључује објављивање догађаја или поруке пре урезивања промена у локалну базу података.
Обе методе имају своје недостатке и само су делимично безбедне за комуникацију у дистрибуираним системима.
Ово је дијаграм секвенце примене првог приступа.
У овом сценарију, услуга за подношење захтева за зајам користи приступ Прво-локално-учини-па-објави , где прво обавезује трансакцију, а затим покушава да пошаље обавештење другом систему. Међутим, овај процес је подложан неуспеху ако, на пример, постоје проблеми са мрежом, услуга процене није доступна или услуга за пријаву зајма наиђе на грешку Нема довољно меморије (ООМ) и руши. У таквим случајевима, порука би била изгубљена, остављајући Процену без обавештења о новом захтеву за кредит, осим ако се не примене додатне мере.
И други.
У сценарију „Прво објављивање-па-локално обавезивање“ , услуга апликације за кредит суочава се са значајнијим ризицима. Може да обавести Службу за процену о новој апликацији, али не успе да сачува ово ажурирање локално због проблема као што су проблеми са базом података, грешке у меморији или грешке у коду. Овај приступ може довести до значајних недоследности у подацима, што би могло да изазове озбиљне проблеме, у зависности од тога како Служба за преглед кредита обрађује долазне апликације.
Стога морамо идентификовати решење које нуди робустан механизам за објављивање догађаја спољним потрошачима. Али, пре него што уђемо у потенцијална решења, прво треба да разјаснимо врсте гаранција испоруке порука које се могу постићи у дистрибуираним системима.
Постоје четири врсте гаранција које можемо постићи.
Без гаранција
Не постоји гаранција да ће порука бити испоручена на одредиште. Приступ Прво-Локално-учини-па-објави је управо о томе. Потрошачи могу примити поруке једном, више пута или никада.
Највише једном испоруком
Највише једном испорука значи да ће порука бити достављена на одредиште највише 1 пут. Приступ Прво-Локално-учини-па-објави се може имплементирати на овај начин и са политиком поновног покушаја покушаја са једном вредношћу.
Најмање једном испорука\Потрошачи ће примити и обрадити сваку поруку, али могу примити исту поруку више пута.
Тачно једном испоруком\Тачно једном испоруком значи да ће потрошач примити поруку ефективно једном.
Технички, то је могуће постићи са Кафкиним трансакцијама и специфичном идемпотентном имплементацијом произвођача и потрошача.
У већини случајева, гаранције испоруке „барем једном“ решавају многа питања тако што осигуравају да се поруке испоруче бар једном, али потрошачи морају бити идемпотентни. Међутим, с обзиром на неизбежне кварове на мрежи, сва потрошачка логика мора бити идемпотентна да би се избегла обрада дуплих порука, без обзира на гаранције произвођача. Стога, овај захтев није толико недостатак колико одражава стварност.
Постоји много решења за овај проблем, која имају своје предности и мане.
Према Википедији, Тво-Пхасе Цоммит (2ПЦ) је протокол дистрибуираних трансакција који се користи у рачунарским наукама и системима за управљање базама података како би се осигурала конзистентност и поузданост дистрибуираних трансакција. Дизајниран је за ситуације у којима више ресурса (нпр. базе података) треба да учествују у једној трансакцији, и осигурава да или сви обаве трансакцију или да је сви прекину, чиме се одржава конзистентност података. Звучи управо оно што нам треба, али двофазни урезивање има неколико недостатака:
Најочигледније решење за архитектуру микросервиса је примена шаблона (или чак понекад анти-обрасца) — дељене базе података. Овај приступ је веома интуитиван ако вам је потребна конзистентност трансакција у више табела у различитим базама података, само користите једну заједничку базу података за ове микросервисе.
Недостаци овог приступа укључују увођење једне тачке квара, спречавање независног скалирања базе података и ограничавање могућности коришћења различитих решења базе података која су најприкладнија за специфичне захтеве и случајеве употребе. Поред тога, модификације кодних база микросервиса биле би неопходне да би се подржао такав облик дистрибуиране трансакције.
„ Трансакционо одлазно сандуче “ је образац дизајна који се користи у дистрибуираним системима како би се обезбедило поуздано ширење порука, чак и када су у питању непоуздани системи за размену порука. То укључује чување догађаја у назначеној табели 'ОутбокЕвентс' унутар исте трансакције као и сама операција. Овај приступ је добро усклађен са својствима АЦИД релационих база података. Насупрот томе, многе Но-СКЛ базе података не подржавају у потпуности својства АЦИД, већ се опредељују за принципе ЦАП теореме и БАСЕ филозофије, које дају приоритет доступности и коначној доследности у односу на строгу доследност.
Трансакционо одлазно сандуче обезбеђује најмање једном гаранцију и може се применити на неколико приступа:
Праћење дневника трансакција
Поллинг публисхер
Приступ праћења евиденције трансакција подразумева коришћење решења специфичних за базу података као што је ЦДЦ (Цханге Дата Цаптуре). Главни недостаци овог приступа су:
Специфична решења за базе података
Повећано кашњење због специфичности имплементације ЦДЦ-а
Други метод је Поллинг Публисхер , који олакшава отпремање одлазног сандучета анкетирањем табеле одлазног сандучета. Примарни недостатак овог приступа је потенцијал за повећање оптерећења базе података, што може довести до већих трошкова. Штавише, не подржавају све Но-СКЛ базе података ефикасно испитивање специфичних сегмената документа. Издвајање читавих докумената може, стога, довести до деградације перформанси.
Ево малог дијаграма секвенце који објашњава како то функционише.
Примарни изазов са шаблоном Трансакционог излазног сандучета лежи у његовој зависности од АЦИД својстава базе података. То може бити једноставно у типичним ОЛТП базама података, али представља изазове у области НоСКЛ. Да би се ово решило, потенцијално решење је да се користи дневник додавања (на пример, Кафка) одмах од покретања обраде захтева.
Уместо да директно обрађујемо команду 'поднеси захтев за кредит', ми је одмах шаљемо интерној Кафкиној теми, а затим клијенту враћамо 'прихваћени' резултат. Међутим, пошто је велика вероватноћа да команда још увек треба да се обради, не можемо одмах обавестити купца о резултату. Да бисмо управљали овом коначном конзистентношћу, можемо да користимо технике као што су дуго испитивање, анкетирање које покреће клијент, оптимистична ажурирања корисничког интерфејса или коришћење ВебСоцкетс-а или Сервер-Сент Евентс за обавештења. Међутим, ово је сасвим посебна тема, па да се вратимо на нашу почетну тему.
Послали смо поруку на интерну Кафкину тему. Служба за пријаву зајма затим конзумира ову поруку — исту команду коју је примила од клијента — и почиње са обрадом. Прво, извршава неку пословну логику; тек након што се ова логика успешно спроведе и резултати се задрже, објављује нове поруке о јавној Кафкиној теми.
Хајде да погледамо мало псеудо-кода.
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(); }
Шта ако обрада пословне логике не успе? Без бриге, пошто померање још није извршено, порука ће бити поново покушана.
Шта ако слање нових догађаја Кафки не успе? Без бриге, пошто је пословна логика идемпотентна, неће креирати дупликат захтева за кредит. Уместо тога, покушаће да поново пошаље поруке јавној Кафкиној теми.
Шта ако се поруке шаљу Кафки, али урезивање померања не успе? Без бриге, пошто је пословна логика идемпотентна, неће направити дупликат захтева за кредит. Уместо тога, поново ће слати поруке јавној Кафкиној теми и надати се да ће урезивање офсета овог пута успети.
Главни недостаци овог приступа укључују додатну сложеност повезану са новим стилом програмирања, коначну доследност (пошто клијент неће одмах знати резултат) и захтев да сва пословна логика буде идемпотентна.
Шта је извор догађаја и како се може применити овде? Извор догађаја је софтверски архитектонски образац који се користи за моделирање стања система хватањем свих промена његових података као низа непроменљивих догађаја. Ови догађаји представљају чињенице или прелазе стања и служе као једини извор истине за тренутно стање система. Дакле, технички, имплементацијом система за извор догађаја, ми већ имамо све догађаје у ЕвентСторе-у, а потрошачи могу користити овај ЕвентСторе као једини извор истине о томе шта се догодило. Нема потребе за посебним решењем базе података за праћење свих промена или забринутости око наручивања, једини проблем је седење на страни за читање јер је за добијање стварног стања ентитета потребно да се сви догађаји поново репродукују.
У овом чланку смо прегледали неколико приступа за изградњу поуздане размене порука у дистрибуираним системима. Постоји неколико препорука које бисмо могли узети у обзир приликом изградње система са овим карактеристикама
Следећи пут ћемо погледати практичнији пример имплементације Трансакционог излазног сандучета. Види
ти!