HighLoad++, Михаил Тјуленев (MongoDB): Причинска конзистентност: од теорија до пракса

Следната конференција HighLoad++ ќе се одржи на 6 и 7 април 2020 година во Санкт Петербург.
Детали и билети по ссылке. HighLoad++ Сибир 2019. Сала „Краснојарск“. 25 јуни, 12:00 часот. Тези и презентација.

HighLoad++, Михаил Тјуленев (MongoDB): Причинска конзистентност: од теорија до пракса

Се случува практичните барања да се во конфликт со теоријата, каде што аспектите важни за комерцијален производ не се земаат предвид. Овој говор претставува процес за избор и комбинирање на различни пристапи за создавање на компоненти за причинско-последична конзистентност врз основа на академско истражување засновано на барањата на комерцијален производ. Слушателите ќе научат за постоечките теоретски пристапи за логички часовници, следење на зависност, безбедност на системот, синхронизација на часовникот и зошто MongoDB се реши на одредени решенија.

Михаил Тјуленев (во натамошниот текст: МТ): – Ќе зборувам за Каузална конзистентност - ова е карактеристика на која работевме во MongoDB. Работам во група на дистрибуирани системи, тоа го направивме пред околу две години.

HighLoad++, Михаил Тјуленев (MongoDB): Причинска конзистентност: од теорија до пракса

Во тој процес, морав да се запознаам со многу академски истражувања, бидејќи оваа карактеристика е доста добро проучена. Се покажа дека ниту една статија не се вклопува во она што се бара во производствената база на податоци поради многу специфични барања кои веројатно се присутни во секоја производна апликација.

Ќе зборувам за тоа како ние, како потрошувачи на академско истражување, подготвуваме нешто од него што потоа можеме да им го претставиме на нашите корисници како готово јадење кое е погодно и безбедно за употреба.

Причинска конзистентност. Ајде да ги дефинираме концептите

За почеток, сакам да кажам генерално што е причинска конзистентност. Има два лика - Леонард и Пени (ТВ серија „The Big Bang Theory“):

HighLoad++, Михаил Тјуленев (MongoDB): Причинска конзистентност: од теорија до пракса

Да речеме дека Пени е во Европа и Леонард сака да и приреди забава со изненадување. И тој не може да смисли ништо подобро од тоа да ја исфрли од списокот на пријатели, испраќајќи им на сите свои пријатели ажурирање на изворот: „Ајде да ја направиме Пени среќна!“ (таа е во Европа, додека спие, сето ова не го гледа и не може да го види, бидејќи ја нема). На крајот, таа ја брише оваа објава, ја брише од доводот и го враќа пристапот за да не забележи ништо и да нема скандал.
Сето ова е добро и добро, но да претпоставиме дека системот е дистрибуиран и работите тргнаа малку наопаку. Може, на пример, да се случи ограничувањето на пристапот на Пени да се случи по појавувањето на оваа објава, ако настаните не се поврзани по причина и последица. Всушност, ова е пример кога е потребна причинска конзистентност за да се изврши деловна функција (во овој случај).

Всушност, ова се сосема нетривијални својства на базата на податоци - многу малку луѓе ги поддржуваат. Да преминеме на моделите.

Модели на конзистентност

Што точно е модел на конзистентност во базите на податоци? Ова се некои од гаранциите што ги дава дистрибуираниот систем за тоа кои податоци може да ги прими клиентот и по кој редослед.

Во принцип, сите модели на конзистентност се сведуваат на тоа колку е сличен дистрибуираниот систем со систем што работи, на пример, на еден јазол на лаптоп. И вака сличен е системот што работи на илјадници гео-дистрибуирани „јазли“ со лаптоп, во кој сите овие својства во принцип се извршуваат автоматски.

Затоа, моделите на конзистентност се применуваат само на дистрибуирани системи. Сите системи кои претходно постоеле и работеле со исто вертикално скалирање не доживеале такви проблеми. Имаше еден Buffer Cache и од него секогаш се читаше сè.

Модел Силен

Всушност, првиот модел е Силен (или линијата за способност за подем, како што често се нарекува). Ова е модел на конзистентност кој гарантира дека секоја промена, откако ќе се потврди дека се случила, е видлива за сите корисници на системот.

Ова создава глобален редослед на сите настани во базата на податоци. Ова е својство на многу силна конзистентност, и генерално е многу скапо. Сепак, тоа е многу добро поддржано. Тоа е само многу скапо и бавно - само ретко се користи. Ова се нарекува способност за кревање.

Постои уште една, посилна сопственост што е поддржана во Spanner - наречена Надворешна конзистентност. Ќе зборуваме за тоа малку подоцна.

Предизвикувачки

Следниот е Каузал, токму за што зборував. Има уште неколку поднивоа помеѓу Силно и Каузално за кои нема да зборувам, но сите тие се сведуваат на Причинска. Ова е важен модел бидејќи е најсилниот од сите модели, најсилната конзистентност во присуство на мрежа или партиции.

Причините се всушност ситуација во која настаните се поврзани со причинско-последична врска. Многу често тие се перцепирани како Прочитајте ги вашите права од гледна точка на клиентот. Ако клиентот забележал некои вредности, тој не може да ги види вредностите што биле во минатото. Тој веќе почнува да гледа читања на префиксот. Се се сведува на истото.
Причините како модел на конзистентност е делумно подредување на настани на серверот, во кое настаните од сите клиенти се набљудуваат во иста низа. Во овој случај, Леонард и Пени.

Евентуално

Третиот модел е евентуална конзистентност. Тоа го поддржуваат апсолутно сите дистрибуирани системи, минималниот модел кој воопшто има смисла. Тоа значи следново: кога имаме некои промени во податоците, во одреден момент тие стануваат конзистентни.

Во таков момент таа не кажува ништо, инаку би се претворила во Надворешна конзистентност - тоа би било сосема друга приказна. Сепак, ова е многу популарен модел, најчест. Стандардно, сите корисници на дистрибуирани системи користат евентуална конзистентност.

Сакам да дадам неколку компаративни примери:

HighLoad++, Михаил Тјуленев (MongoDB): Причинска конзистентност: од теорија до пракса

Што значат овие стрели?

  • Латентност. Како што се зголемува јачината на конзистентноста, таа станува поголема од очигледни причини: треба да направите повеќе записи, да добиете потврда од сите домаќини и јазли кои учествуваат во кластерот дека податоците се веќе таму. Соодветно на тоа, Евентуалната конзистентност го има најбрзиот одговор, бидејќи таму, како по правило, можете дури и да го посветите на меморија и тоа, во принцип, ќе биде доволно.
  • Достапност. Ако го разбереме ова како способност на системот да реагира во присуство на прекини на мрежата, партиции или некој вид дефект, толеранцијата на грешки се зголемува како што се намалува моделот на конзистентност, бидејќи ни е доволно да живее еден домаќин и во истото времето произведува некои податоци. Евентуалната конзистентност воопшто не гарантира ништо за податоците - може да биде се.
  • Аномалии. Во исто време, се разбира, се зголемува бројот на аномалии. Во силната конзистентност тие речиси и да не постојат воопшто, но во евентуалната конзистентност тие можат да бидат што било. Се поставува прашањето: зошто луѓето избираат евентуална конзистентност ако таа содржи аномалии? Одговорот е дека моделите за евентуална конзистентност се применливи и дека постојат аномалии, на пример, во краток временски период; можно е да се користи волшебникот за читање и повеќе или помалку читање конзистентни податоци; Често е можно да се користат модели со силна конзистентност. Во пракса ова функционира и често бројот на аномалии е временски ограничен.

CAP теорема

Кога ќе ги видите зборовите конзистентност, достапност - што ви паѓа на ум? Така е - теорема CAP! Сега сакам да го отфрлам митот... Не сум јас - тоа е Мартин Клепман, кој напиша прекрасна статија, прекрасна книга.

HighLoad++, Михаил Тјуленев (MongoDB): Причинска конзистентност: од теорија до пракса

Теоремата CAP е принцип формулиран во 2000-тите дека конзистентност, достапност, партиции: земете било кои две и не можете да изберете три. Тоа беше одреден принцип. Тоа беше докажано како теорема неколку години подоцна од Гилберт и Линч. Потоа ова почна да се користи како мантра - системите почнаа да се делат на CA, CP, AP и така натаму.

Оваа теорема всушност беше докажана за следните случаи... Прво, Достапноста се сметаше не како континуирана вредност од нула до стотици (0 - системот е „мртов“, 100 - брзо реагира; ние сме навикнати да го разгледуваме така) , но како својство на алгоритмот , кој гарантира дека за сите негови извршување враќа податоци.

Воопшто нема збор за време на одговор! Постои алгоритам кој враќа податоци по 100 години - апсолутно прекрасен достапен алгоритам, кој е дел од теоремата CAP.
Второ: теоремата беше докажана за промени во вредностите на истиот клуч, и покрај фактот што овие промени се менуваат во големина. Тоа значи дека во реалноста тие практично не се користат, бидејќи моделите се различни Евентуална конзистентност, силна конзистентност (можеби).

За што е сето ова? Згора на тоа, теоремата CAP токму во формата во која беше докажана практично не е применлива и ретко се користи. Во теоретска форма некако се ограничува. Излегува одреден принцип што е интуитивно точен, но генерално не е докажан.

Каузалната конзистентност е најсилниот модел

Она што се случува сега е дека можете да ги добиете сите три работи: конзистентност, достапност користејќи партиции. Конкретно, Каузалната конзистентност е најсилниот модел на конзистентност, кој сè уште функционира во присуство на партиции (паузи во мрежата). Затоа е од толку голем интерес и затоа се зафативме.

HighLoad++, Михаил Тјуленев (MongoDB): Причинска конзистентност: од теорија до пракса

Прво, ја поедноставува работата на развивачите на апликации. Особено, присуството на голема поддршка од серверот: кога сите записи што се појавуваат во еден клиент се гарантира дека ќе пристигнат во иста секвенца на друг клиент. Второ, издржува партиции.

Внатрешна кујна MongoDB

Сеќавајќи се дека е ручек, се префрламе во кујната. Ќе ви кажам за моделот на системот, имено, што е MongoDB за оние кои првпат слушаат за таква база на податоци.

HighLoad++, Михаил Тјуленев (MongoDB): Причинска конзистентност: од теорија до пракса

HighLoad++, Михаил Тјуленев (MongoDB): Причинска конзистентност: од теорија до пракса

MongoDB (во натамошниот текст „MongoDB“) е дистрибуиран систем кој поддржува хоризонтално скалирање, односно сечење; и во секој фрагмент поддржува и вишок на податоци, односно репликација.

Sharding во MongoDB (не релациска база на податоци) врши автоматско балансирање, односно секоја збирка документи (или „табела“ во однос на релационите податоци) е поделена на парчиња, а серверот автоматски ги преместува меѓу деловите.

Рутерот Query, кој дистрибуира барања, за клиентот е некој клиент преку кој работи. Веќе знае каде и кои податоци се наоѓаат и ги насочува сите барања до правилниот дел.

Друга важна точка: MongoDB е единствен господар. Има едно основно - може да земе записи што ги поддржуваат клучевите што ги содржи. Не можете да пишувате Multi-master.

Направивме издание 4.2 - таму се појавија нови интересни работи. Конкретно, тие вметнаа Lucene - пребарување - имено извршна јава директно во Mongo, и таму стана можно да се вршат пребарувања преку Lucene, исто како и во Еластика.

И направија нов производ - графикони, достапен е и на Atlas (сопствениот Облак на Монго). Тие имаат бесплатен ниво - можете да си играте со него. Навистина ми се допаднаа графиконите - визуелизација на податоци, многу интуитивна.

Состојки Причинска конзистентност

Набројав околу 230 написи кои се објавени на оваа тема - од Лесли Ламперт. Сега од моја меморија ќе ви пренесам некои делови од овие материјали.

HighLoad++, Михаил Тјуленев (MongoDB): Причинска конзистентност: од теорија до пракса

Сè започна со една статија на Лесли Ламперт, напишана во 1970-тите. Како што можете да видите, некои истражувања на оваа тема сè уште се во тек. Сега Каузалната конзистентност доживува интерес во врска со развојот на дистрибуирани системи.

Ограничувања

Какви ограничувања постојат? Ова е всушност една од главните точки, бидејќи ограничувањата што ги наметнува производствениот систем се многу различни од ограничувањата што постојат во академските статии. Тие често се прилично вештачки.

HighLoad++, Михаил Тјуленев (MongoDB): Причинска конзистентност: од теорија до пракса

  • Прво, „MongoDB“ е единствен господар, како што веќе реков (ова во голема мера го поедноставува).
  • Сметаме дека системот треба да поддржува околу 10 илјади парчиња. Не можеме да донесеме никакви архитектонски одлуки кои експлицитно ќе ја ограничат оваа вредност.
  • Имаме облак, но претпоставуваме дека човекот сепак треба да има можност кога ќе преземе бинарно, ќе го стартува на својот лаптоп и се работи одлично.
  • Претпоставуваме нешто што Истражувањето ретко го претпоставува: надворешните клиенти можат да прават што сакаат. MongoDB е со отворен код. Според тоа, клиентите можат да бидат толку паметни и лути - тие можат да сакаат да скршат сè. Шпекулираме дека можеби потекнуваат византиски феилори.
  • За надворешни клиенти кои се надвор од периметарот, постои важно ограничување: ако оваа функција е оневозможена, тогаш не треба да се забележи деградација на перформансите.
  • Друга точка е генерално антиакадемска: компатибилноста на претходните и идните верзии. Старите драјвери мора да поддржуваат нови ажурирања, а базата на податоци мора да поддржува стари драјвери.

Во принцип, сето ова наметнува ограничувања.

Компоненти на причинска конзистентност

Сега ќе зборувам за некои од компонентите. Ако ја земеме предвид Каузалната конзистентност воопшто, можеме да избереме блокови. Избравме од дела кои припаѓаат на одреден блок: Следење на зависност, избор на часовници, како овие часовници може да се синхронизираат еден со друг и како обезбедуваме безбедност - ова е груб преглед на она за што ќе зборувам:

HighLoad++, Михаил Тјуленев (MongoDB): Причинска конзистентност: од теорија до пракса

Целосно следење на зависност

Зошто е потребно? Така што кога податоците се реплицираат, секој запис, секоја промена на податоците содржи информации за тоа од какви промени зависи. Првата и наивна промена е кога секоја порака што содржи запис содржи информации за претходните пораки:

HighLoad++, Михаил Тјуленев (MongoDB): Причинска конзистентност: од теорија до пракса

Во овој пример, бројот во кадрави загради е рекордните броеви. Понекогаш овие записи со вредности дури се пренесуваат во целост, понекогаш се пренесуваат некои верзии. Заклучокот е дека секоја промена содржи информации за претходната (очигледно сето ова го носи во себе).

Зошто решивме да не го користиме овој пристап (целосно следење)? Очигледно, бидејќи овој пристап е непрактичен: секоја промена на социјалната мрежа зависи од сите претходни промени на таа социјална мрежа, пренесувајќи, да речеме, Facebook или VKontakte при секое ажурирање. Како и да е, има многу истражувања за следење на целосна зависност - ова се предсоцијални мрежи; за некои ситуации тоа навистина функционира.

Експлицитно следење на зависност

Следниот е поограничен. Овде се разгледува и преносот на информации, но само она што е јасно зависно. Што зависи од тоа што, по правило, го одредува Апликацијата. Кога податоците се реплицираат, барањето враќа одговори само кога претходните зависности се задоволени, односно прикажани. Ова е суштината на тоа како функционира Каузалната конзистентност.

HighLoad++, Михаил Тјуленев (MongoDB): Причинска конзистентност: од теорија до пракса

Таа гледа дека записот 5 зависи од записите 1, 2, 3, 4 - соодветно, таа чека пред клиентот да има пристап до промените направени со одлуката за пристап на Пени, кога сите претходни промени веќе поминале низ базата на податоци.

Ниту ова не ни одговара, бидејќи се уште има премногу информации и ќе ги забави работите. Има и друг пристап...

Часовник Лампорт

Тие се многу стари. Lamport Clock значи дека овие зависности се преклопени во скаларна функција, која се нарекува Lamport Clock.

Скаларна функција е некој апстрактен број. Често се нарекува логично време. Со секој настан, овој бројач се зголемува. Бројачот, кој моментално му е познат на процесот, ја испраќа секоја порака. Јасно е дека процесите може да не се синхронизираат, може да имаат сосема различни времиња. Сепак, системот некако го балансира часовникот со такви пораки. Што се случува во овој случај?

Го поделив тој голем дел на два за да биде јасно: Пријателите можат да живеат во еден јазол, кој содржи дел од колекцијата, а Feed може да живеат во друг јазол, кој содржи дел од оваа колекција. Дали е јасно како можат да излезат од линијата? Прво навестување ќе каже: „Реплицирано“, а потоа Пријатели. Ако системот не обезбеди некаква гаранција дека Feed нема да се прикаже додека не се испорачаат и зависностите на Пријатели во колекцијата Пријатели, тогаш ќе ја имаме токму ситуацијата што ја спомнав.

Гледате како логично се зголемува времето на бројачот на Feed:

HighLoad++, Михаил Тјуленев (MongoDB): Причинска конзистентност: од теорија до пракса

Значи, главното својство на овој Lamport Clock и Causal конзистентност (објаснето преку Lamport Clock) е ова: ако имаме настани A и B, а настанот B зависи од настанот A*, тогаш следува дека логичното време на настанот A е помало од LogicalTime од настанот Б.

* Понекогаш тие исто така велат дека А се случило пред Б, односно А се случило пред Б - ова е одредена врска што делумно го наредува целиот сет на настани што се случиле воопшто.

Спротивното е неточно. Ова е всушност една од главните недостатоци на Lamport Clock - делумна нарачка. Постои концепт за симултани настани, односно настани во кои ниту (А се случило пред Б) ниту (А се случило пред Б). Пример би бил паралелното додавање на Леонард на некој друг како пријател (ни Леонард, туку Шелдон, на пример).
Ова е својството што често се користи при работа со часовниците на Лампорт: тие конкретно ја гледаат функцијата и од ова заклучуваат дека можеби овие настани се зависни. Затоа што еден начин е точен: ако LogicalTime A е помало од LogicalTime B, тогаш B не може да се случи пред A; и ако повеќе, тогаш можеби.

Векторски часовник

Логичниот развој на часовникот Лампорт е Векторски часовник. Тие се разликуваат по тоа што секој јазол што е овде содржи свој посебен часовник и тие се пренесуваат како вектор.
Во овој случај, гледате дека нултиот индекс на векторот е одговорен за Feed, а првиот индекс на векторот е за Friends (секој од овие јазли). И сега тие ќе се зголемат: нултиот индекс на „Feed“ се зголемува при пишување - 1, 2, 3:

HighLoad++, Михаил Тјуленев (MongoDB): Причинска конзистентност: од теорија до пракса

Зошто векторскиот часовник е подобар? Бидејќи тие ви дозволуваат да откриете кои настани се симултани и кога се случуваат на различни јазли. Ова е многу важно за систем за споделување како MongoDB. Сепак, не го избравме ова, иако е прекрасна работа, и одлично функционира, а веројатно би ни одговарала...

Ако имаме 10 илјади парчиња, не можеме да пренесеме 10 илјади компоненти, дури и ако ги компресираме или смислиме нешто друго - носивоста сепак ќе биде неколку пати помала од волуменот на целиот овој вектор. Затоа, стегајќи ги срцата и забите, го напуштивме овој пристап и преминавме на друг.

Клач TrueTime. Атомски часовник

Реков дека ќе има приказна за Спанер. Ова е одлична работа, директно од XNUMX век: атомски часовници, GPS синхронизација.

Која е идејата? „Spanner“ е систем на Google кој неодамна стана достапен дури и за луѓето (тие додадоа SQL на него). Секоја трансакција таму има одреден временски печат. Бидејќи времето е синхронизирано*, на секој настан може да му се додели одредено време - атомските часовници имаат време на чекање, по што се гарантира дека ќе се „случи“ различно време.

HighLoad++, Михаил Тјуленев (MongoDB): Причинска конзистентност: од теорија до пракса

Така, со едноставно пишување во базата на податоци и чекање одреден временски период, сериозноста на настанот автоматски се гарантира. Тие го имаат најсилниот модел на Конзистентност што може да се замисли во принцип - тоа е Надворешна конзистентност.

* Ова е главниот проблем со Lampart часовниците - тие никогаш не се синхрони на дистрибуирани системи. Тие можат да се разминуваат; дури и со NTP, тие сè уште не работат многу добро. „Spanner“ има атомски часовник и синхронизацијата, се чини, е микросекунди.

Зошто не избравме? Не претпоставуваме дека нашите корисници имаат вграден атомски часовник. Кога ќе се појават, вградени во секој лаптоп, ќе има некаква супер кул GPS синхронизација - тогаш да... Но засега најдоброто што е можно е Амазон, Базни станици - за фанатици... Затоа користевме други часовници .

Хибриден часовник

Ова е всушност она што функционира во MongoDB кога се обезбедува причинска конзистентност. Како се хибридни? Хибридот е скаларна вредност, но има две компоненти:

HighLoad++, Михаил Тјуленев (MongoDB): Причинска конзистентност: од теорија до пракса

  • Првата е епохата на Unix (колку секунди поминаа од „почетокот на компјутерскиот свет“).
  • Вториот е одреден прираст, исто така 32-битен непотпишан инт.

Тоа е се, всушност. Постои овој пристап: делот кој е одговорен за времето е синхронизиран со часовникот цело време; секогаш кога се случува ажурирање, овој дел се синхронизира со часовникот и излегува дека времето е секогаш повеќе или помалку точно, а зголемувањето ви овозможува да правите разлика помеѓу настаните што се случиле во исто време.

Зошто е ова важно за MongoDB? Затоа што ви овозможува да направите некој вид резервни ресторани во одреден момент во времето, односно настанот е индексиран по време. Ова е важно кога се потребни одредени настани; За базата на податоци, настаните се промени во базата на податоци што се случиле во одредени временски интервали.

Најважната причина ќе ти ја кажам само тебе (те молам, не кажувај никому)! Ова го направивме затоа што вака изгледаат организираните, индексирани податоци во MongoDB OpLog. OpLog е структура на податоци која ги содржи апсолутно сите промени во базата на податоци: тие прво одат во OpLog, а потоа се применуваат на самиот Storage во случај кога станува збор за реплициран датум или фрагмент.

Ова беше главната причина. Сепак, постојат и практични барања за развој на база на податоци, што значи дека таа треба да биде едноставна - малку код, што е можно помалку скршени работи кои треба да се препишат и тестираат. Фактот дека нашите оплогови беа индексирани со хибридни часовници многу помогна и ни овозможи да го направиме вистинскиот избор. Навистина се исплатеше и некако магично работеше на првиот прототип. Беше многу кул!

Синхронизација на часовникот

Постојат неколку методи за синхронизација опишани во научната литература. Зборувам за синхронизација кога имаме два различни фрагменти. Ако има еден сет реплика, нема потреба од никаква синхронизација: ова е „еден господар“; имаме OpLog, во кој спаѓаат сите промени - во овој случај, сè е веќе последователно наредено во самиот „Oplog“. Но, ако имаме два различни фрагменти, тука е важна синхронизацијата на времето. Еве каде векторскиот часовник помогна повеќе! Но, ние ги немаме.

HighLoad++, Михаил Тјуленев (MongoDB): Причинска конзистентност: од теорија до пракса

Вториот е погоден - ова е „отчукувања на срцето“. Можно е да се разменат некои сигнали кои се јавуваат секоја единица време. Но, отчукувањата на срцето се премногу бавни, не можеме да обезбедиме латентност на нашиот клиент.

Вистинското време е, се разбира, прекрасна работа. Но, повторно, ова е веројатно иднината... Иако веќе може да се направи во Atlas, веќе има брзи „Амазон“ синхронизатори на времето. Но, тоа нема да биде достапно за секого.

Озборувањето е кога сите пораки вклучуваат време. Ова е приближно она што го користиме. Секоја порака помеѓу јазли, двигател, рутер за податочен јазол, апсолутно сè за MongoDB е некој вид елемент, компонента на базата на податоци што содржи часовник што работи. Секаде имаат значење на хибридно време, се пренесува. 64 бита? Ова дозволува, ова е можно.

Како сето тоа функционира заедно?

Еве јас гледам на една реплика сет за да го олеснам. Постојат примарни и секундарни. Секундарното прави репликација и не е секогаш целосно синхронизирано со примарното.

Се појавува вметнување во „Пример“ со одредена временска вредност. Ова вметнување го зголемува внатрешното броење за 11, ако ова е максимумот. Или ќе ги провери вредностите на часовникот и ќе се синхронизира со часовникот ако вредностите на часовникот се поголеми. Ова ви овозможува да се организирате според времето.

Откако ќе ја направи снимката, настанува важен момент. Часовникот е во „MongoDB“ и се зголемува само во случај на пишување на „Oplog“. Ова е настан кој ја менува состојбата на системот. Апсолутно во сите класични статии, настан се смета кога пораката удира во јазол: пораката пристигнала, што значи дека системот ја променил својата состојба.

Ова се должи на фактот што во текот на истражувањето не е сосема јасно како ќе се толкува оваа порака. Со сигурност знаеме дека ако не се одрази во „Оплог“, тогаш нема да се толкува на кој било начин, а промената на состојбата на системот е само запис во „Оплог“. Ова ни поедноставува сè: моделот го поедноставува и ни овозможува да го организираме во еден комплет реплика и многу други корисни работи.

Вр пораката. Тој вели: „Ми треба сè што се случи барем по 12 или за време на дванаесет“ (види слика погоре).

Ова е она што се нарекува Причинска конзистентна (CAT). Теоретски постои таков концепт дека ова е одреден дел од времето, што е конзистентно само по себе. Во овој случај, можеме да кажеме дека ова е состојбата на системот што беше забележана во времето 12.

Сега сè уште нема ништо овде, бидејќи овој вид ја симулира ситуацијата кога ви треба секундарниот да реплицира податоци од примарниот. Тој чека... И сега пристигнаа податоците - тој ги враќа овие вредности.

HighLoad++, Михаил Тјуленев (MongoDB): Причинска конзистентност: од теорија до пракса

Тоа е речиси како сето тоа функционира. За малку.

Што значи „речиси“? Да претпоставиме дека има некој што прочитал и разбрал како функционира сето ова. Сфатив дека секогаш кога се појавува ClusterTime, тој го ажурира внатрешниот логички часовник, а потоа следниот запис се зголемува за еден. Оваа функција зема 20 линии. Да речеме дека ова лице го пренесува најголемиот 64-битен број, минус еден.

Зошто „минус еден“? Бидејќи внатрешниот часовник ќе биде заменет со оваа вредност (очигледно, ова е најголемото можно и поголемо од сегашното време), тогаш ќе се појави запис во „Оплог“, а часовникот ќе се зголеми за друга единица - и веќе ќе да биде максимална вредност (едноставно ги има сите единици, нема каде да се оди) , несвети инти).

Јасно е дека после ова системот станува апсолутно недостапен за ништо. Може само да се растовари и исчисти - многу рачна работа. Целосна достапност:

HighLoad++, Михаил Тјуленев (MongoDB): Причинска конзистентност: од теорија до пракса

Покрај тоа, ако ова се реплицира на друго место, тогаш целиот кластер едноставно паѓа. Апсолутно неприфатлива ситуација која секој може многу брзо и лесно да ја организира! Затоа, овој момент го сметавме за еден од најважните. Како да се спречи тоа?

Нашиот начин е да потпишеме clusterTime

Така се пренесува во пораката (пред синиот текст). Но, почнавме да генерираме и потпис (син текст):

HighLoad++, Михаил Тјуленев (MongoDB): Причинска конзистентност: од теорија до пракса

Потписот се генерира со клуч што се чува во базата на податоци, во безбеден периметар; самиот се генерира и ажурира (корисниците не гледаат ништо за тоа). Се генерира хаш и секоја порака се потпишува кога се креира и се потврдува кога е примена.
Веројатно се поставува прашањето во главите на луѓето: „Колку тоа ги забавува работите? Ти реков дека треба да работи брзо, особено во отсуство на оваа функција.

Што значи да се користи Каузална конзистентност во овој случај? Ова е за да се прикаже параметарот afterClusterTime. Без ова, во секој случај едноставно ќе помине вредности. Озборувањето, почнувајќи од верзијата 3.6, секогаш функционира.

Ако го оставиме постојаното генерирање на потписи, тоа ќе го забави системот дури и во отсуство на карактеристика, која не ги задоволува нашите пристапи и барања. Па што направивме?

Направете го тоа брзо!

Тоа е прилично едноставна работа, но трикот е интересен - ќе го споделам, можеби некој ќе биде заинтересиран.
Имаме хаш што ги чува потпишаните податоци. Сите податоци минуваат низ кешот. Кешот не го потпишува конкретното време, туку опсегот. Кога ќе пристигне одредена вредност, генерираме опсег, ги маскираме последните 16 бита и ја потпишуваме оваа вредност:

HighLoad++, Михаил Тјуленев (MongoDB): Причинска конзистентност: од теорија до пракса

Со добивањето на таков потпис, го забрзуваме системот (релативно) 65 илјади пати. Работи одлично: кога спроведувавме експерименти, времето всушност се намали за 10 илјади пати кога имавме секвенцијално ажурирање. Јасно е дека кога тие се во судир, тоа не функционира. Но, во повеќето практични случаи тоа функционира. Комбинацијата на потписот Range заедно со потписот го реши безбедносниот проблем.

Што научивме?

Лекции што ги научивме од ова:

  • Треба да читаме материјали, приказни, статии, бидејќи имаме многу интересни работи. Кога работиме на некоја карактеристика (особено сега, кога правевме трансакции итн.), треба да читаме и разбереме. Потребно е време, но всушност е многу корисно затоа што јасно покажува каде сме. Се чинеше дека не смисливме ништо ново - само ги земавме состојките.

    Генерално, постои одредена разлика во размислувањето кога има академска конференција (Сигмон, на пример) - сите се фокусираат на нови идеи. Што е ново за нашиот алгоритам? Тука нема ништо посебно ново. Новитетот повеќе лежи во начинот на кој ги споивме постоечките пристапи. Затоа, првото нешто е да ги прочитате класиците, почнувајќи од Лампарт.

  • Во производството, барањата се сосема различни. Сигурен сум дека многу од вас не се соочуваат со „сферични“ бази на податоци во апстрактен вакуум, туку со нормални, реални работи кои имаат проблеми со достапноста, латентноста и толеранцијата на грешки.
  • Последното нешто е што моравме да погледнеме различни идеи и да комбинираме неколку сосема различни написи во еден пристап, заедно. Идејата за потпишување, на пример, генерално произлезе од една статија која го разгледуваше протоколот Паксос, кој за невизантиските неуспешни е внатре во протоколот за овластување, за византиските - надвор од протоколот за овластување... Во принцип, токму тоа е она што ние заврши со тоа.

    Нема апсолутно ништо ново овде! Но, штом сето тоа го измешавме... Тоа е исто како да се каже дека рецептот за салата Оливие е глупост, бидејќи јајцата, мајонезот и краставиците се веќе измислени... Се работи за истата приказна.

HighLoad++, Михаил Тјуленев (MongoDB): Причинска конзистентност: од теорија до пракса

Ќе завршам со ова. Ви благодарам!

прашања

Прашање од публиката (во натамошниот текст Б): – Ти благодарам, Михаил, за извештајот! Темата за времето е интересна. Вие користите озборување. Рекоа дека секој си има свое време, секој си го знае локалното време. Како што разбрав, имаме драјвер - може да има многу клиенти со драјвери, планери за прашања, исто така, фрагменти... И на што се сведува системот ако наеднаш имаме несовпаѓање: некој одлучи дека е за минута напред, некој минута позади? Каде ќе стигнеме?

МТ: – Навистина одлично прашање! Само сакав да зборувам за фрагменти. Ако правилно го разбрав прашањето, ја имаме следнава ситуација: има фрагмент 1 и фрагмент 2, читањето се јавува од овие два фрагменти - тие имаат несовпаѓање, не комуницираат меѓу себе, бидејќи времето што го знаат е различно, особено времето кога тие постојат во оплоги.
Да речеме дека фрагментот 1 направи милион записи, фрагментот 2 не направи ништо, а барањето дојде до два парчиња. И првиот има afterClusterTime од над милион. Во таква ситуација, како што објаснив, фрагментот 2 никогаш нема воопшто да одговори.

НА: – Сакав да знам како се синхронизираат и избираат едно логично време?

МТ: - Многу лесно да се синхронизирате. Шард, кога afterClusterTime ќе дојде кај него и тој не најде време во „Оплог“, иницира без одобрение. Тоа е, тој го подигнува своето време со рацете на оваа вредност. Ова значи дека нема настани што одговараат на ова барање. Тој го создава овој настан вештачки и на тој начин станува Каузален конзистентен.

НА: – Што ако после ова му дојдат некои други настани што се изгубени некаде во мрежата?

МТ: – Shard е дизајниран на таков начин што нема да дојдат повторно, бидејќи е единствен мајстор. Ако веќе се пријавил, тогаш нема да дојдат, туку ќе дојдат подоцна. Не може да се случи нешто да се заглави некаде, потоа да не пишува, а потоа да пристигнат овие настани - и причинската конзистентност е скршена. Кога не пишува, сите треба да дојдат на ред (ќе ги чека).

HighLoad++, Михаил Тјуленев (MongoDB): Причинска конзистентност: од теорија до пракса

НА: – Имам неколку прашања во врска со редиците. Причинската конзистентност претпоставува дека постои одредена редица на дејства што треба да се извршат. Што се случува ако исчезне еден од нашите пакети? Еве дојде 10-ти, 11-ти... 12-ти исчезна, а сите други чекаат да се оствари. И одеднаш нашиот автомобил загина, не можеме да направиме ништо. Дали има максимална должина на редот што се акумулира пред да се изврши? Каков фатален неуспех се случува кога ќе се изгуби некоја состојба? Згора на тоа, ако запишеме дека има некоја претходна состојба, тогаш некако треба да тргнеме од неа? Но, тие не го оттурнаа!

МТ: – Исто така одлично прашање! Што правиме? MongoDB има концепт на кворум пишува, кворум чита. Во кои случаи пораката може да се изгуби? Кога пишувањето не е кворум или кога читањето не е кворум (може да се залепи и некаков вид ѓубре).
Во однос на Каузалната конзистентност, беше спроведен голем експериментален тест, чиј резултат беше дека во случај кога запишувањето и читањето не се кворум, се јавуваат нарушувања на причинско-последичната конзистентност. Токму тоа што го кажуваш!

Наш совет: користете барем читање кворум кога користите Каузална конзистентност. Во овој случај, ништо нема да се изгуби, дури и ако записот за кворум е изгубен... Ова е ортогонална ситуација: ако корисникот не сака да се изгубат податоците, тој треба да користи запис за кворум. Причинската конзистентност не гарантира издржливост. Издржливоста е загарантирана со репликација и машини поврзани со репликација.

НА: – Кога создаваме инстанца што ни врши шардирање (не господар, туку роб, соодветно), тој се потпира на времето на Unix на сопствената машина или на времето на „господарот“; Дали се синхронизира за прв пат или периодично?

МТ: – Сега ќе објаснам. Shard (т.е. хоризонтална партиција) - таму секогаш има Примарна. А фрагментот може да има „господар“ и може да има реплики. Но, фрагментот секогаш поддржува снимање, бидејќи мора да поддржува некој домен (парчето има Примарно).

НА: – Значи се зависи чисто од „господарот“? Дали секогаш се користи мастер времето?

МТ: - Да. Можете фигуративно да кажете: часовникот отчукува кога ќе се појави влез во „господарот“, во „Оплог“.

НА: – Имаме клиент кој се поврзува и не треба да знае ништо за времето?

МТ: – Воопшто ништо не треба да знаете! Ако зборуваме за тоа како тоа функционира на клиентот: кога клиентот сака да користи Причинска конзистентност, тој треба да отвори сесија. Сега сè е таму: трансакции во сесијата и преземање права... Сесија е подредување на логички настани што се случуваат со клиентот.

Ако ја отвори оваа сесија и таму каже дека сака причинска конзистентност (ако сесијата стандардно поддржува Причинска конзистентност), сè работи автоматски. Возачот се сеќава на ова време и го зголемува кога ќе добие нова порака. Се сеќава каков одговор вратил претходниот од серверот што ги вратил податоците. Следното барање ќе содржи afterCluster („време поголемо од ова“).

Клиентот не треба да знае апсолутно ништо! Ова за него е целосно непроѕирно. Ако луѓето ги користат овие карактеристики, што можат да направат? Прво, можете безбедно да читате секундарни содржини: можете да пишувате на Примарно и да читате од географски реплицираните секундари и да бидете сигурни дека тоа функционира. Во исто време, сесиите што биле снимени на Примарна може дури и да се префрлат на Секундарна, т.е. можете да користите не една, туку неколку.

НА: – Нов слој на компјутерска наука – типови на податоци CRDT (Реплицирани типови на податоци без конфликт) – е силно поврзан со темата Евентуална конзистентност. Дали размислувавте да ги интегрирате овие типови податоци во базата на податоци и што можете да кажете за тоа?

МТ: - Добро прашање! CRDT има смисла за конфликти за пишување: во MongoDB, еден господар.

НА: – Имам прашање од devops. Во реалниот свет, има такви језуитски ситуации кога се случува Византискиот неуспех, а злите луѓе внатре во заштитениот периметар почнуваат да ѕиркаат во протоколот, да испраќаат занаетчиски пакети на посебен начин?

HighLoad++, Михаил Тјуленев (MongoDB): Причинска конзистентност: од теорија до пракса

МТ: – Злите луѓе внатре во периметарот се како тројански коњ! Злобните луѓе внатре во периметарот можат да направат многу лоши работи.

НА: – Јасно е дека оставајќи, грубо кажано, дупка на серверот низ која можете да ставите зоолошка градина со слонови и засекогаш да го срушите целиот кластер... Ќе треба време за рачно закрепнување... Ова, благо кажано, е погрешно. Од друга страна, ова е интересно: во реалниот живот, во пракса, постојат ситуации кога природно се случуваат слични внатрешни напади?

МТ: – Бидејќи ретко се среќавам со безбедносни прекршувања во реалниот живот, не можам да кажам дали се случуваат. Но, ако зборуваме за развојната филозофија, размислуваме вака: имаме периметар кој им обезбедува на момците кои вршат безбедност - ова е замок, ѕид; а внатре во периметарот можете да правите што сакате. Јасно е дека има корисници со можност само за прегледување, а има и корисници со можност за бришење на директориумот.

Во зависност од правата, штетата што корисниците можат да ја направат може да биде глушец или слон. Јасно е дека корисникот со целосни права може да направи сè. Корисникот со ограничени права може да предизвика значително помала штета. Конкретно, не може да го скрши системот.

НА: – Во заштитениот периметар, некој се обиде да создаде неочекувани протоколи за серверот со цел целосно да го уништи серверот, а ако имате среќа, целиот кластер... Дали некогаш добива толку „добро“?

МТ: „Никогаш не сум слушнал за такви работи“. Фактот дека можете да го урнете серверот на овој начин не е тајна. Неуспешно внатре, да се биде од протоколот, да се биде овластен корисник кој може да напише вакво нешто во пораката... Всушност, тоа е невозможно, бидејќи сепак ќе се потврди. Можно е да се оневозможи оваа автентикација за корисници кои не ја сакаат - тогаш тоа е нивен проблем; тие, грубо кажано, самите ги уништија ѕидовите и таму можеш да турнеш слон, кој ќе гази... Ама во глобала, можеш да се дотераш како мајстор, дојди да го извлечеш!

НА: – Благодарам за извештајот. Сергеј (Јандекс). Постои константа во Монг што го ограничува бројот на членови со право на глас во множеството на реплики, а оваа константа е 7 (седум). Зошто е ова константа? Зошто ова не е некој вид параметар?

МТ: – Имаме Replica Sets со 40 јазли. Секогаш има мнозинство. Не знам која верзија...

НА: – Во Replica Set можете да управувате со членови без право на глас, но има најмногу 7 членови со право на глас. Како можеме да го преживееме исклучувањето во овој случај ако нашиот Replica Set е распространет низ 3 центри за податоци? Еден центар за податоци може лесно да се исклучи, а друга машина може да испадне.

МТ: – Ова е веќе малку надвор од опсегот на извештајот. Ова е општо прашање. Можеби ќе можам да ви кажам за тоа подоцна.

HighLoad++, Михаил Тјуленев (MongoDB): Причинска конзистентност: од теорија до пракса

Некои реклами 🙂

Ви благодариме што останавте со нас. Дали ви се допаѓаат нашите написи? Сакате да видите поинтересна содржина? Поддржете не со нарачка или препорака на пријатели, облак VPS за програмери од 4.99 долари, уникатен аналог на сервери на почетно ниво, кој беше измислен од нас за вас: Целата вистина за VPS (KVM) E5-2697 v3 (6 јадра) 10GB DDR4 480GB SSD 1Gbps од 19 долари или како да споделите сервер? (достапен со RAID1 и RAID10, до 24 јадра и до 40 GB DDR4).

Dell R730xd 2 пати поевтин во центарот за податоци Equinix Tier IV во Амстердам? Само овде 2 x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 телевизор од 199 долари во Холандија! Dell R420 - 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB - од 99 долари! Прочитајте за Како да се изгради инфраструктурна корп. класа со употреба на сервери Dell R730xd E5-2650 v4 вредни 9000 евра за денар?

Извор: www.habr.com

Додадете коментар