HighLoad++, Michail Tyulenev (MongoDB): Kauzální konzistence: od teorie k praxi

Příští konference HighLoad++ se bude konat 6. a 7. dubna 2020 v St. Petersburgu.
Podrobnosti a vstupenky по ссылке. HighLoad++ Siberia 2019. Hala "Krasnojarsk". 25. června, 12:00. Teze a představení.

HighLoad++, Michail Tyulenev (MongoDB): Kauzální konzistence: od teorie k praxi

Stává se, že praktické požadavky jsou v rozporu s teorií, kde se neberou v úvahu aspekty důležité pro komerční produkt. Tato přednáška představuje proces výběru a kombinování různých přístupů k vytváření komponent kauzální konzistence na základě akademického výzkumu založeného na požadavcích komerčního produktu. Posluchači se dozvědí o existujících teoretických přístupech k logickým hodinám, sledování závislostí, zabezpečení systému, synchronizaci hodin a proč se MongoDB rozhodl pro určitá řešení.

Michail Tyuleněv (dále jen MT): – Budu mluvit o kauzální konzistenci – to je funkce, na které jsme pracovali v MongoDB. Pracuji ve skupině distribuovaných systémů, dělali jsme to asi před dvěma lety.

HighLoad++, Michail Tyulenev (MongoDB): Kauzální konzistence: od teorie k praxi

V tomto procesu jsem se musel seznámit s mnoha akademickými výzkumy, protože tato funkce byla docela dobře prozkoumána. Ukázalo se, že ani jeden článek nezapadá do toho, co je požadováno v produkční databázi, kvůli velmi specifickým požadavkům, které jsou pravděpodobně přítomny v jakékoli produkční aplikaci.

Budu mluvit o tom, jak z něj jako konzumenti akademického Výzkumu připravujeme něco, co pak můžeme předložit našim uživatelům jako hotové jídlo, které je pohodlné a bezpečné.

Kauzální konzistence. Pojďme si definovat pojmy

Na úvod bych chtěl obecně říci, co je to Kauzální konzistence. Existují dvě postavy - Leonard a Penny (televizní seriál "The Big Bang Theory"):

HighLoad++, Michail Tyulenev (MongoDB): Kauzální konzistence: od teorie k praxi

Řekněme, že Penny je v Evropě a Leonard jí chce uspořádat večírek s překvapením. A nenapadá ho nic lepšího, než ji vyhodit ze svého seznamu přátel a poslat všem svým přátelům aktuální informace o zdroji: "Udělejme Penny šťastnou!" (je v Evropě, zatímco spí, tohle všechno nevidí a nevidí, protože tam není). Nakonec tento příspěvek smaže, vymaže z Feedu a obnoví přístup, aby si ničeho nevšimla a nevznikl žádný skandál.
To vše je v pořádku, ale předpokládejme, že systém je distribuován a věci se trochu pokazily. Může se například stát, že k omezení přístupu Penny došlo poté, co se objevil tento příspěvek, pokud události nesouvisejí příčinou a následkem. Ve skutečnosti se jedná o příklad, kdy je k plnění obchodní funkce (v tomto případě) vyžadována kauzální konzistence.

Ve skutečnosti jde o docela netriviální vlastnosti databáze – málokdo je podporuje. Pojďme k modelům.

Modely konzistence

Co přesně je model konzistence v databázích? To jsou některé ze záruk, které distribuovaný systém poskytuje o tom, jaká data může klient přijímat a v jakém pořadí.

V zásadě všechny modely konzistence vycházejí z toho, jak podobný je distribuovaný systém systému, který běží například na jednom uzlu na notebooku. A takto je systém, který běží na tisících geograficky distribuovaných „uzlů“, podobný notebooku, ve kterém se všechny tyto vlastnosti provádějí v zásadě automaticky.

Proto jsou modely konzistence aplikovány pouze na distribuované systémy. Všechny systémy, které dříve existovaly a fungovaly ve stejném vertikálním měřítku, takové problémy nezaznamenaly. Existovala jedna vyrovnávací paměť a z ní se vždy načetlo vše.

Model Silný

Vlastně úplně prvním modelem je Strong (nebo linie schopností vzestupu, jak se tomu často říká). Jedná se o model konzistence, který zajišťuje, že každá změna, jakmile je potvrzena, že k ní došlo, je viditelná pro všechny uživatele systému.

Tím se vytvoří globální pořadí všech událostí v databázi. Toto je velmi silná konzistentní vlastnost a je obecně velmi drahá. Je však velmi dobře podporován. Je to jen velmi drahé a pomalé - jen se používá zřídka. Tomu se říká schopnost vzestupu.

Ve Spanneru je podporována další, silnější vlastnost – nazvaná External Consistency. Promluvíme si o tom trochu později.

Kauzální

Další je Causal, což je přesně to, o čem jsem mluvil. Mezi Strong a Causal je několik dalších podúrovní, o kterých nebudu mluvit, ale všechny se scvrkají na Causal. Toto je důležitý model, protože je nejsilnější ze všech modelů, nejsilnější konzistence v přítomnosti sítě nebo oddílů.

Kauzality jsou vlastně situace, kdy jsou události spojeny vztahem příčina-následek. Velmi často jsou z pohledu klienta vnímány jako Read your on rights. Pokud klient pozoroval nějaké hodnoty, nemůže vidět hodnoty, které byly v minulosti. Už začíná vidět předpony. Z toho všeho vychází to samé.
Causals jako model konzistence je částečné řazení událostí na serveru, ve kterém jsou události od všech klientů sledovány ve stejném pořadí. V tomto případě Leonard a Penny.

Eventuální

Třetí model je Eventual Consistency. Toto podporují naprosto všechny distribuované systémy, minimální model, který má vůbec smysl. Znamená to následující: když máme nějaké změny v datech, v určitém okamžiku se stanou konzistentními.

V takové chvíli nic neříká, jinak by se proměnila ve Vnější konzistenci – to by byl úplně jiný příběh. Přesto se jedná o velmi oblíbený model, nejrozšířenější. Ve výchozím nastavení všichni uživatelé distribuovaných systémů používají Eventual Consistency.

Chci uvést několik srovnávacích příkladů:

HighLoad++, Michail Tyulenev (MongoDB): Kauzální konzistence: od teorie k praxi

Co znamenají tyto šipky?

  • Latence. S rostoucí silou konzistence se ze zřejmých důvodů zvětšuje: musíte vytvořit více záznamů, získat potvrzení od všech hostitelů a uzlů, které se účastní clusteru, že data již existují. Eventual Consistency má tedy nejrychlejší odpověď, protože tam si ji zpravidla můžete uložit i do paměti a to bude v zásadě stačit.
  • Dostupnost. Pokud to chápeme jako schopnost systému reagovat na přerušení sítě, oddíly nebo nějaký druh selhání, odolnost proti chybám se zvyšuje se snižujícím se modelem konzistence, protože nám stačí, že jeden hostitel žije a zároveň čas produkuje nějaká data. Eventual Consistency nezaručuje o datech vůbec nic – může to být cokoliv.
  • Anomálie. Zároveň se samozřejmě zvyšuje počet anomálií. V Strong Consistency by téměř vůbec neměly existovat, ale v Eventual Consistency mohou být čímkoli. Nabízí se otázka: proč lidé volí Eventual Consistency, pokud obsahuje anomálie? Odpověď zní, že modely eventuální konzistence jsou použitelné a anomálie existují například v krátkém časovém období; je možné pomocí průvodce číst a víceméně číst konzistentní data; Často je možné použít modely silné konzistence. V praxi to funguje a často je počet anomálií časově omezený.

CAP věta

Když vidíte slova konzistence, dostupnost – co vás napadne? To je pravda - CAP teorém! Teď chci vyvrátit mýtus... To nejsem já – to je Martin Kleppmann, který napsal úžasný článek, nádhernou knihu.

HighLoad++, Michail Tyulenev (MongoDB): Kauzální konzistence: od teorie k praxi

Teorém CAP je princip formulovaný v roce 2000, že konzistence, dostupnost, oddíly: vezměte libovolné dva a nemůžete si vybrat tři. Byl to určitý princip. To bylo prokázáno jako teorém o několik let později Gilbertem a Lynchem. Pak se to začalo používat jako mantra – systémy se začaly dělit na CA, CP, AP a tak dále.

Tato věta byla skutečně prokázána pro následující případy... Za prvé, dostupnost nebyla považována za spojitou hodnotu od nuly do stovek (0 - systém je „mrtvý“, 100 - reaguje rychle; jsme zvyklí to tak uvažovat) , ale jako vlastnost algoritmu, který zaručuje, že pro všechna jeho provedení vrací data.

O době odezvy tam není vůbec slovo! Existuje algoritmus, který vrací data po 100 letech – naprosto úžasný dostupný algoritmus, který je součástí CAP teorému.
Za druhé: teorém byl prokázán pro změny hodnot stejného klíče, a to navzdory skutečnosti, že tyto změny lze měnit. To znamená, že ve skutečnosti se prakticky nepoužívají, protože modely jsou různé Eventual Consistency, Strong Consistency (možná).

K čemu to všechno je? Navíc teorém CAP přesně v té podobě, v jaké byl prokázán, je prakticky nepoužitelný a používá se jen zřídka. V teoretické podobě to vše nějak omezuje. Ukazuje se určitý princip, který je intuitivně správný, ale obecně nebyl prokázán.

Kauzální konzistence je nejsilnější model

Nyní se děje to, že můžete získat všechny tři věci: Konzistenci, Dostupnost pomocí oddílů. Zejména kauzální konzistence je nejsilnější model konzistence, který stále funguje v přítomnosti oddílů (přerušení v síti). Proto je o to tak velký zájem, a proto jsme se toho chopili.

HighLoad++, Michail Tyulenev (MongoDB): Kauzální konzistence: od teorie k praxi

Za prvé zjednodušuje práci vývojářům aplikací. Zejména přítomnost skvělé podpory ze serveru: kdy všechny záznamy, které se vyskytují uvnitř jednoho klienta, zaručeně dorazí ve stejném pořadí na jiného klienta. Za druhé, odolává přepážkám.

Vnitřní kuchyně MongoDB

S vědomím, že je oběd, se přesuneme do kuchyně. Řeknu vám o modelu systému, konkrétně o tom, co je MongoDB pro ty, kteří o takové databázi slyší poprvé.

HighLoad++, Michail Tyulenev (MongoDB): Kauzální konzistence: od teorie k praxi

HighLoad++, Michail Tyulenev (MongoDB): Kauzální konzistence: od teorie k praxi

MongoDB (dále jen „MongoDB“) je distribuovaný systém, který podporuje horizontální škálování, tedy sharding; a v rámci každého shardu podporuje i redundanci dat, tedy replikaci.

Sdílení v MongoDB (ne relační databáze) provádí automatické vyvažování, to znamená, že každá kolekce dokumentů (nebo „tabulka“ z hlediska relačních dat) je rozdělena na části a server je automaticky přesouvá mezi shardy.

Směrovač dotazů, který distribuuje požadavky pro klienta, je nějaký klient, jehož prostřednictvím funguje. Už ví, kde a jaká data se nacházejí, a všechny požadavky nasměruje na správný shard.

Další důležitý bod: MongoDB je jediný master. Existuje jeden primární – může přijímat záznamy, které podporují klíče, které obsahuje. Nemůžete psát Multi-master.

Udělali jsme vydání 4.2 - objevily se tam nové zajímavé věci. Konkrétně vložili Lucene - search - konkrétně spustitelnou javu přímo do Monga a tam bylo možné provádět vyhledávání přes Lucene, stejně jako v Elastice.

A udělali nový produkt - Charts, ten je dostupný i na Atlasu (Mongův vlastní Cloud). Mají bezplatnou úroveň – můžete si s ní pohrát. Moc se mi líbily Charts - vizualizace dat, velmi intuitivní.

Složení Kauzální konzistence

Napočítal jsem asi 230 článků, které na toto téma vyšly – od Leslie Lamperta. Nyní vám z mé paměti poskytnu některé části těchto materiálů.

HighLoad++, Michail Tyulenev (MongoDB): Kauzální konzistence: od teorie k praxi

Vše začalo článkem Leslieho Lamperta, který byl napsán v 1970. letech minulého století. Jak vidíte, nějaký výzkum na toto téma stále probíhá. Kauzální konzistence nyní zažívá zájem v souvislosti s rozvojem distribuovaných systémů.

Omezení

Jaká omezení existují? To je vlastně jeden z hlavních bodů, protože omezení, která produkční systém ukládá, se velmi liší od omezení, která existují v akademických článcích. Často jsou dost umělé.

HighLoad++, Michail Tyulenev (MongoDB): Kauzální konzistence: od teorie k praxi

  • Za prvé, „MongoDB“ je jediný master, jak jsem již řekl (toto značně zjednodušuje).
  • Domníváme se, že systém by měl podporovat zhruba 10 tisíc shardů. Nemůžeme dělat žádná architektonická rozhodnutí, která tuto hodnotu výslovně omezí.
  • Máme cloud, ale předpokládáme, že člověk by měl mít stále možnost, když si stáhne binární, spustí to na svém notebooku a vše funguje skvěle.
  • Předpokládáme něco, co Výzkum jen zřídka předpokládá: externí klienti si mohou dělat, co chtějí. MongoDB je open source. V souladu s tím mohou být klienti tak chytří a naštvaní - mohou chtít všechno rozbít. Spekulujeme, že byzantští Feilors mohou pocházet.
  • Pro externí klienty, kteří jsou mimo perimetr, existuje důležité omezení: pokud je tato funkce zakázána, nemělo by docházet k žádnému snížení výkonu.
  • Další bod je obecně protiakademický: kompatibilita předchozích verzí a budoucích. Staré ovladače musí podporovat nové aktualizace a databáze musí podporovat staré ovladače.

To vše obecně ukládá omezení.

Složky příčinné konzistence

Nyní budu mluvit o některých komponentách. Pokud vezmeme v úvahu kauzální konzistenci obecně, můžeme vybrat bloky. Vybírali jsme z prací, které patří do určitého bloku: Dependency Tracking, výběr hodin, jak se tyto hodiny dají vzájemně synchronizovat a jak zajistíme bezpečnost – to je hrubý nástin toho, o čem budu mluvit:

HighLoad++, Michail Tyulenev (MongoDB): Kauzální konzistence: od teorie k praxi

Úplné sledování závislosti

Proč je to potřeba? Takže když jsou data replikována, každý záznam, každá změna dat obsahuje informace o tom, na kterých změnách závisí. Úplně první a naivní změna je, když každá zpráva obsahující záznam obsahuje informace o předchozích zprávách:

HighLoad++, Michail Tyulenev (MongoDB): Kauzální konzistence: od teorie k praxi

V tomto příkladu jsou čísla ve složených závorkách čísla záznamů. Někdy jsou tyto záznamy s hodnotami dokonce přenášeny celé, někdy jsou přenášeny některé verze. Základem je, že každá změna obsahuje informace o té předchozí (to vše v sobě samozřejmě nese).

Proč jsme se rozhodli nepoužít tento přístup (plné sledování)? Je zřejmé, že tento přístup je nepraktický: jakákoli změna sociální sítě závisí na všech předchozích změnách této sociální sítě, řekněme na Facebooku nebo VKontakte v každé aktualizaci. Přesto existuje mnoho výzkumů o Full Dependency Tracking – jedná se o předsociální sítě, v některých situacích to opravdu funguje.

Explicitní sledování závislostí

Další je omezenější. Je zde uvažován i přenos informací, ale pouze těch, které jsou jednoznačně závislé. Co na čem závisí, zpravidla určuje Aplikace. Když jsou data replikována, dotaz vrací odpovědi pouze tehdy, když byly splněny předchozí závislosti, to znamená, že jsou zobrazeny. To je podstata toho, jak funguje Kauzální konzistence.

HighLoad++, Michail Tyulenev (MongoDB): Kauzální konzistence: od teorie k praxi

Vidí, že záznam 5 závisí na záznamech 1, 2, 3, 4 – podle toho čeká, než bude mít klient přístup ke změnám provedeným rozhodnutím Penny o přístupu, když všechny předchozí změny již prošly databází.

To nám také nevyhovuje, protože informací je stále příliš mnoho a věci to zpomalí. Existuje i jiný přístup...

Hodiny Lamport

Jsou velmi staré. Lamport Clock znamená, že tyto závislosti jsou složeny do skalární funkce, která se nazývá Lamport Clock.

Skalární funkce je nějaké abstraktní číslo. Často se mu říká logický čas. S každou událostí se tento čítač zvyšuje. Čítač, který je aktuálně procesu znám, odešle každou zprávu. Je jasné, že procesy mohou být nesynchronizované, mohou mít úplně jiné časy. Přesto systém nějak vyrovnává hodiny s takovým zasíláním zpráv. Co se stane v tomto případě?

Rozdělil jsem ten velký úlomek na dva, aby bylo jasno: Přátelé mohou žít v jednom uzlu, který obsahuje část sbírky, a zdroj může žít v jiném uzlu, který obsahuje část této sbírky. Je jasné, jak mohou vybočit z řady? První zdroj řekne: „Replikováno“ a poté Přátelé. Pokud systém neposkytuje nějakou záruku, že se Feed nezobrazí, dokud nebudou doručeny i závislosti Friends v kolekci Friends, pak nastane přesně ta situace, kterou jsem zmínil.

Vidíte, jak se logicky zvyšuje doba počítadla ve zdroji:

HighLoad++, Michail Tyulenev (MongoDB): Kauzální konzistence: od teorie k praxi

Takže hlavní vlastnost těchto Lamportových hodin a kauzální konzistence (vysvětlená prostřednictvím Lamportových hodin) je tato: pokud máme Události A a B a událost B závisí na události A*, pak z toho vyplývá, že Logický čas události A je menší než Logický čas z události B.

* Někdy se také říká, že A se stalo před B, tedy A se stalo před B - to je určitý vztah, který částečně řídí celý soubor událostí, které se obecně staly.

Opak je nesprávný. To je vlastně jedna z hlavních nevýhod Lamport Clock - částečná objednávka. Existuje koncept simultánních událostí, to znamená událostí, ve kterých se ani (A nestalo před B) ani (A stalo před B). Příkladem může být Leonardovo paralelní přidání někoho jiného jako přítele (ani ne Leonarda, ale například Sheldona).
Toto je vlastnost, která se často používá při práci s hodinami Lamport: Dívají se konkrétně na funkci a z toho usuzují, že možná jsou tyto události závislé. Protože jeden způsob je pravdivý: pokud je Logický čas A menší než Logický čas B, pak B nemůže nastat před A; a když víc, tak možná.

Vektorové hodiny

Logickým vývojem Lamportových hodin jsou vektorové hodiny. Liší se tím, že každý uzel, který zde je, obsahuje vlastní samostatné hodiny a jsou přenášeny jako vektor.
V tomto případě vidíte, že nultý index vektoru je zodpovědný za zdroj a první index vektoru je za přátele (každý z těchto uzlů). A nyní se zvýší: nulový index „Feed“ se při psaní zvyšuje – 1, 2, 3:

HighLoad++, Michail Tyulenev (MongoDB): Kauzální konzistence: od teorie k praxi

Proč jsou Vector Clock lepší? Protože vám umožňují zjistit, které události jsou simultánní a kdy k nim dochází na různých uzlech. To je velmi důležité pro systém sharding, jako je MongoDB. Toto jsme si však nevybrali, ač je to báječná věc, a funguje skvěle a asi by se nám hodila...

Pokud máme 10 tisíc střepů, nemůžeme přenést 10 tisíc komponent, i když to zkomprimujeme nebo vymyslíme něco jiného - užitečné zatížení bude stále několikanásobně menší než objem celého tohoto vektoru. Proto jsme se skřípěním srdce a zubů tento přístup opustili a přešli k jinému.

Spanner TrueTime. Atomové hodiny

Řekl jsem, že bude příběh o Spannerovi. To je skvělá věc, přímo z XNUMX. století: atomové hodiny, synchronizace GPS.

Co je to za nápad? „Spanner“ je systém Google, který se nedávno dokonce stal dostupným lidem (přidali do něj SQL). Každá transakce tam má nějaké časové razítko. Vzhledem k tomu, že čas je synchronizován*, lze každé události přiřadit konkrétní čas – atomové hodiny mají čekací dobu, po které je zaručeno, že „nastane jiný čas“.

HighLoad++, Michail Tyulenev (MongoDB): Kauzální konzistence: od teorie k praxi

Pouhým zápisem do databáze a čekáním po určitou dobu je tedy automaticky zaručena serializovatelnost události. Mají nejsilnější model konzistence, který si lze v principu představit – je to Externí konzistence.

* Toto je hlavní problém s hodinami Lampart – na distribuovaných systémech nejsou nikdy synchronní. Mohou se rozcházet; dokonce i s NTP stále nefungují příliš dobře. "Spanner" má atomové hodiny a synchronizace, zdá se, je mikrosekunda.

Proč jsme si nevybrali? Nepředpokládáme, že naši uživatelé mají vestavěné atomové hodiny. Až se objeví, budou zabudovány do každého notebooku, bude tam nějaká super cool GPS synchronizace - pak ano... Ale zatím nejlepší, co je možné, je Amazon, Base Stations - pro fanatiky... Takže jsme použili jiné hodinky .

Hybridní hodiny

To je vlastně to, co tiká v MongoDB při zajišťování kauzální konzistence. Jak jsou hybridní? Hybrid je skalární hodnota, ale má dvě složky:

HighLoad++, Michail Tyulenev (MongoDB): Kauzální konzistence: od teorie k praxi

  • První je epocha Unixu (kolik sekund uplynulo od „počátku počítačového světa“).
  • Druhý je nějaký přírůstek, také 32bitový unsigned int.

To je vlastně všechno. Existuje tento přístup: část, která je zodpovědná za čas, je neustále synchronizována s hodinami; pokaždé, když dojde k aktualizaci, je tato část synchronizována s hodinami a ukazuje se, že čas je vždy více či méně správný a inkrement vám umožňuje rozlišovat mezi událostmi, které nastaly ve stejný okamžik.

Proč je to důležité pro MongoDB? Protože vám to umožňuje vytvořit nějaký druh záložních restaurací v určitém okamžiku, to znamená, že událost je indexována podle času. To je důležité, když jsou potřeba určité události; U databáze jsou událostmi změny v databázi, ke kterým došlo v určitých časových intervalech.

Ten nejdůležitější důvod vám řeknu pouze vám (prosím, nikomu to neříkejte)! Udělali jsme to, protože takto vypadají organizovaná indexovaná data v MongoDB OpLog. OpLog je datová struktura, která obsahuje absolutně všechny změny v databázi: nejprve jdou do OpLogu a poté jsou aplikovány na samotné úložiště v případě, že se jedná o replikované datum nebo fragment.

To byl hlavní důvod. Stále existují také praktické požadavky na vývoj databáze, což znamená, že by měla být jednoduchá – málo kódu, co nejméně rozbitých věcí, které je třeba přepisovat a testovat. Skutečnost, že naše oplogy byly indexovány hybridními hodinami, hodně pomohla a umožnila nám udělat správnou volbu. To se opravdu vyplatilo a tak nějak magicky fungovalo na úplně prvním prototypu. Bylo to velmi cool!

Synchronizace hodin

Ve vědecké literatuře je popsáno několik synchronizačních metod. Mluvím o synchronizaci, když máme dva různé střepy. Pokud existuje jedna sada replik, není potřeba žádná synchronizace: jedná se o „single master“; máme OpLog, do kterého spadají všechny změny - v tomto případě je vše již sekvenčně řazeno v samotném “Oplogu”. Pokud ale máme dva různé střípky, je zde důležitá synchronizace času. Tady vektorové hodiny pomohly více! Ale my je nemáme.

HighLoad++, Michail Tyulenev (MongoDB): Kauzální konzistence: od teorie k praxi

Druhý je vhodný - to je „Heartbeats“. Je možné vyměňovat některé signály, které se vyskytují každou jednotku času. Ale tepy jsou příliš pomalé, nemůžeme našemu klientovi poskytnout latenci.

Skutečný čas je samozřejmě úžasná věc. Ale to je zase asi budoucnost... I když už to lze udělat v Atlasu, už existují rychlé „Amazonské“ synchronizátory času. Ale nebude dostupná všem.

Pomlouvání je, když všechny zprávy obsahují čas. To je přibližně to, co používáme. Každá zpráva mezi uzly, ovladač, router datového uzlu, úplně všechno pro MongoDB je nějaký prvek, komponenta databáze, která obsahuje hodiny, které běží. Všude mají význam hybridního času, ten se přenáší. 64 bitů? To umožňuje, to je možné.

Jak to všechno dohromady funguje?

Tady se dívám na jednu sadu replik, abych to trochu usnadnil. Existují primární a sekundární. Sekundární provádí replikaci a není vždy zcela synchronizována s primárním.

Dojde k vložení do „Primery“ s určitou časovou hodnotou. Tato vložka zvyšuje vnitřní počet o 11, pokud je to maximum. Nebo zkontroluje hodnoty hodin a synchronizuje se s hodinami, pokud jsou hodnoty hodin větší. To vám umožní organizovat podle času.

Poté, co pořídí nahrávku, nastává důležitý okamžik. Hodiny jsou v "MongoDB" a jsou inkrementovány pouze v případě zápisu do "Oplog". Toto je událost, která změní stav systému. Absolutně ve všech klasických článcích se za událost považuje, když zpráva zasáhne uzel: zpráva dorazila, což znamená, že systém změnil svůj stav.

Je to dáno tím, že během výzkumu není zcela jasné, jak bude toto sdělení interpretováno. S jistotou víme, že pokud se to neprojeví v „Oplogu“, nebude to nijak interpretováno a změna stavu systému je pouze záznamem v „Oplogu“. To nám vše zjednodušuje: model to zjednodušuje a umožňuje nám to uspořádat do jedné sady replik a mnoho dalších užitečných věcí.

Hodnota, která je již zapsána do „Oplog“ je vrácena – víme, že „Oplog“ již tuto hodnotu obsahuje a jeho čas je 12. Nyní, řekněme, čtení začíná z jiného uzlu (sekundárního) a vysílá afterClusterTime v zpráva. Říká: „Potřebuji všechno, co se stalo alespoň po 12 nebo během dvanácti“ (viz obrázek výše).

Tomu se říká kauzální a konzistentní (CAT). Teoreticky existuje takový koncept, že se jedná o nějaký časový úsek, který je sám o sobě konzistentní. V tomto případě můžeme říci, že toto je stav systému, který byl pozorován v čase 12.

Nyní zde zatím nic není, protože tento druh simuluje situaci, kdy potřebujete sekundární k replikaci dat z primárního. Čeká... A nyní dorazila data – vrací tyto hodnoty zpět.

HighLoad++, Michail Tyulenev (MongoDB): Kauzální konzistence: od teorie k praxi

Takhle to celé funguje. Téměř.

Co znamená "téměř"? Předpokládejme, že existuje někdo, kdo četl a pochopil, jak to všechno funguje. Uvědomil jsem si, že pokaždé, když dojde k ClusterTime, aktualizuje vnitřní logické hodiny a pak se další položka zvýší o jednu. Tato funkce zabere 20 řádků. Řekněme, že tato osoba přenáší největší 64bitové číslo mínus jedna.

Proč "mínus jedna"? Protože vnitřní hodiny budou nahrazeny touto hodnotou (samozřejmě, že je to největší možná a větší než aktuální čas), dojde k záznamu v „Oplog“ a hodiny budou zvýšeny o jinou jednotku – a již budou být maximální hodnota (jsou tam prostě všechny jednotky, není kam jít) , unsaint ints).

Je jasné, že poté se systém stává absolutně nepřístupným pro cokoliv. Dá se pouze vyložit a vyčistit - spousta ruční práce. Plná dostupnost:

HighLoad++, Michail Tyulenev (MongoDB): Kauzální konzistence: od teorie k praxi

Navíc, pokud je toto replikováno někde jinde, pak celý shluk jednoduše spadne. Naprosto nepřijatelná situace, kterou si každý může velmi rychle a snadno zorganizovat! Proto jsme tento moment považovali za jeden z nejdůležitějších. Jak tomu předejít?

Náš způsob je podepsat clusterTime

Takto se to přenáší ve zprávě (před modrým textem). Ale také jsme začali generovat podpis (modrý text):

HighLoad++, Michail Tyulenev (MongoDB): Kauzální konzistence: od teorie k praxi

Podpis je generován klíčem, který je uložen uvnitř databáze, uvnitř zabezpečeného perimetru; se generuje a aktualizuje (uživatelé o tom nic nevidí). Vygeneruje se hash a každá zpráva se při vytvoření podepíše a po přijetí se ověří.
V myslích lidí pravděpodobně vyvstává otázka: "Jak moc to zpomaluje věci?" Řekl jsem vám, že by to mělo fungovat rychle, zvláště pokud tato funkce chybí.

Co v tomto případě znamená použít Kauzální konzistenci? Toto má zobrazit parametr afterClusterTime. Bez toho to stejně jednoduše předá hodnoty. Pomlouvání od verze 3.6 vždy funguje.

Pokud ponecháme neustálé generování podpisů, zpomalí to systém i při absenci funkce, která neodpovídá našim přístupům a požadavkům. Tak co jsme udělali?

Udělejte to rychle!

Je to docela jednoduchá věc, ale trik je zajímavý – podělím se o něj, možná to někoho bude zajímat.
Máme hash, který ukládá podepsaná data. Všechna data procházejí mezipamětí. Cache nepodepisuje konkrétní čas, ale rozsah. Když přijde nějaká hodnota, vygenerujeme rozsah, zamaskujeme posledních 16 bitů a podepíšeme tuto hodnotu:

HighLoad++, Michail Tyulenev (MongoDB): Kauzální konzistence: od teorie k praxi

Přijetím takového podpisu zrychlíme systém (relativně) 65 tisíckrát. Funguje to skvěle: když jsme prováděli experimenty, čas se ve skutečnosti zkrátil 10 tisíckrát, když jsme měli sekvenční aktualizaci. Je jasné, že když jsou v rozporu, tak to nefunguje. Ale ve většině praktických případů to funguje. Kombinace podpisu Range spolu s podpisem vyřešila bezpečnostní problém.

co jsme se naučili?

Poučení, které jsme si z toho vzali:

  • Potřebujeme číst materiály, příběhy, články, protože máme spoustu zajímavých věcí. Když pracujeme na nějaké funkci (zejména teď, když jsme dělali transakce atd.), musíme číst a rozumět. Chce to čas, ale ve skutečnosti je to velmi užitečné, protože je jasné, kde jsme. Zdálo se, že jsme nepřišli s ničím novým – jen jsme vzali ingredience.

    Obecně je určitý rozdíl v myšlení, když je akademická konference (například Sigmon) – každý se zaměřuje na nové myšlenky. Co je nového na našem algoritmu? Není zde žádná zvláštní novinka. Novinka spočívá spíše ve způsobu, jakým jsme spojili stávající přístupy dohromady. Proto je první věcí číst klasiku, počínaje Lampartem.

  • Ve výrobě jsou požadavky úplně jiné. Jsem si jist, že mnozí z vás se nepotýkají s „kulovitými“ databázemi v abstraktním vakuu, ale s normálními, skutečnými věcmi, které mají problémy s dostupností, latencí a odolností proti chybám.
  • Poslední věcí je, že jsme se museli podívat na různé myšlenky a spojit několik zcela odlišných článků do jednoho přístupu, společně. Myšlenka o podepisování například obecně vzešla z článku, který se zabýval protokolem Paxos, který je pro nebyzantské Failory uvnitř autorizačního protokolu, pro byzantské - mimo autorizační protokol... Obecně vzato je to přesně to, co my skončil dělat.

    Tady není absolutně nic nového! Ale jakmile jsme to všechno smíchali... Je to stejné, jako bychom řekli, že recept na salát Olivier je nesmysl, protože vejce, majonéza a okurky už byly vynalezeny... Je to o stejném příběhu.

HighLoad++, Michail Tyulenev (MongoDB): Kauzální konzistence: od teorie k praxi

Skončím s tím. Děkuji!

otázky

Otázka z publika (dále jen B): – Děkuji, Michaile, za zprávu! Téma o čase je zajímavé. Používáte Gosiping. Říkali, že každý má svůj čas, každý zná svůj místní čas. Pokud tomu dobře rozumím, máme řidiče - klientů s ovladači může být mnoho, plánovačů dotazů taky, úlomky taky... A k čemu se ten systém zhroutí, když najednou máme nesrovnalost: někdo se rozhodne, že je pro minutu napřed, někdo minutu pozadu? kde skončíme?

MT: – Opravdu skvělá otázka! Jen jsem chtěl mluvit o střípkách. Pokud správně rozumím otázce, máme následující situaci: existuje střep 1 a střep 2, čtení probíhá z těchto dvou střípků - mají nesrovnalost, neinteragují spolu, protože čas, který znají, je jiný, zejména čas, který existují v oplogech.
Řekněme, že útržek 1 vytvořil milion záznamů, útržek 2 vůbec nic a požadavek přišel na dva úlomky. A první má afterClusterTime přes milion. V takové situaci, jak jsem vysvětlil, shard 2 nikdy nebude reagovat vůbec.

In: – Chtěl jsem vědět, jak se synchronizují a vybírají jeden logický čas?

MT: - Velmi snadná synchronizace. Shard, když k němu přijde afterClusterTime a nenajde čas v „Oplogu“, zahájí neschválení. To znamená, že zvyšuje svůj čas rukama na tuto hodnotu. To znamená, že nemá žádné události odpovídající tomuto požadavku. Vytváří tuto událost uměle a stává se tak kauzální konzistentní.

In: – Co když mu potom přijdou další události, které se ztratily někde v síti?

MT: – Shard je navržen tak, že se už nebudou opakovat, protože je to jediný mistr. Pokud se již přihlásil, tak nepřijdou, ale přijdou později. Nemůže se stát, že se někde něco zasekne, pak nic nenapíše a pak přijdou tyto události – a kauzální konzistence je narušena. Když nic nenapíše, měli by přijít na řadu všichni (bude na ně čekat).

HighLoad++, Michail Tyulenev (MongoDB): Kauzální konzistence: od teorie k praxi

In: – Mám několik otázek ohledně front. Kauzální konzistence předpokládá, že existuje konkrétní fronta akcí, které je třeba provést. Co se stane, když jeden z našich balíčků zmizí? Přichází 10., 11.... 12. zmizelo a všichni ostatní čekají, až se to splní. A najednou nám zemřelo auto, nemůžeme nic dělat. Existuje maximální délka fronty, která se nashromáždí před provedením? Jaké fatální selhání nastane, když je ztracen jeden stát? Navíc, když si zapíšeme, že existuje nějaký předchozí stav, tak bychom z něj měli nějak vycházet? Ale neodstrčili ho!

MT: – Taky skvělá otázka! Co to děláme? MongoDB má koncept kvora zapisuje, kvora čte. V jakých případech může dojít ke ztrátě zprávy? Když zápis není kvórum nebo když čtení není kvorum (může se také držet nějaký druh smetí).
Ohledně kauzální konzistence byl proveden velký experimentální test, jehož výsledkem bylo, že v případě, kdy zápisy a čtení nejsou usnášeníschopné, dochází k porušení kauzální konzistence. Přesně to, co říkáte!

Naše rada: při použití kauzální konzistence používejte alespoň čtení kvora. V tomto případě se nic neztratí, i když se ztratí záznam kvora... Toto je ortogonální situace: pokud uživatel nechce, aby se data ztratila, musí použít záznam kvora. Kauzální konzistence nezaručuje trvanlivost. Trvanlivost je zaručena replikací a strojním zařízením spojeným s replikací.

In: – Když vytvoříme instanci, která za nás provádí sharding (ne master, ale slave), spoléhá se na čas Unixu vlastního stroje nebo na čas „mastera“; Synchronizuje se poprvé nebo pravidelně?

MT: – teď to vysvětlím. Shard (tj. horizontální přepážka) – tam je vždy primární. A střep může mít „mistra“ a mohou existovat repliky. Shard ale vždy podporuje nahrávání, protože musí podporovat nějakou doménu (shard má Primární).

In: – Takže vše závisí čistě na „pánovi“? Je vždy použit mistrovský čas?

MT: - Ano. Obrazně můžete říci: hodiny tikají, když dojde k vstupu do „master“, do „Oplog“.

In: – Máme klienta, který se připojí a nepotřebuje vědět nic o čase?

MT: – Nemusíte vědět vůbec nic! Pokud se budeme bavit o tom, jak to funguje na klientovi: když chce klient použít kauzální konzistenci, potřebuje otevřít relaci. Nyní je tam vše: transakce v relaci a načtení práv... Relace je uspořádání logických událostí, které se vyskytují u klienta.

Pokud otevře tuto relaci a řekne tam, že chce kauzální konzistenci (pokud relace standardně podporuje kauzální konzistenci), vše funguje automaticky. Řidič si tento čas zapamatuje a při přijetí nové zprávy jej zvýší. Pamatuje si, jakou odpověď vrátila předchozí ze serveru, který vrátil data. Další požadavek bude obsahovat afterCluster("čas větší než tento").

Klient nemusí vědět absolutně nic! To je pro něj naprosto neprůhledné. Pokud lidé používají tyto funkce, co mohou dělat? Za prvé, můžete bezpečně číst sekundární: můžete zapisovat do primárních a číst z geograficky replikovaných sekundárních stránek a být si jisti, že to funguje. Zároveň lze relace, které byly zaznamenány na Primární, dokonce převést do Sekundární, tj. můžete použít ne jednu relaci, ale několik.

In: – Nová vrstva výpočetní vědy – datové typy CRDT (bezkonfliktní replikované datové typy) – úzce souvisí s tématem eventuální konzistence. Uvažovali jste o integraci těchto typů dat do databáze a co k tomu můžete říci?

MT: - Dobrá otázka! CRDT má smysl pro konflikty zápisu: v MongoDB, single master.

In: – Mám otázku od devopů. V reálném světě jsou takové jezuitské situace, kdy dojde k Byzantskému selhání a zlí lidé uvnitř chráněného perimetru začnou šťourat do protokolu, speciálním způsobem posílat balíčky?

HighLoad++, Michail Tyulenev (MongoDB): Kauzální konzistence: od teorie k praxi

MT: – Zlí lidé uvnitř perimetru jsou jako trojský kůň! Zlí lidé uvnitř perimetru mohou udělat spoustu špatných věcí.

In: – Je jasné, že ponechání, zhruba řečeno, díry na serveru, kterou můžete prostrčit slony a celý shluk navždy zhroutit... Ruční obnova zabere čas... To, mírně řečeno, je špatně. Na druhou stranu je to zajímavé: v reálném životě, v praxi, dochází k situacím, kdy přirozeně k podobným vnitřním útokům dochází?

MT: – Vzhledem k tomu, že se v reálném životě setkávám s narušeními bezpečnosti jen zřídka, nemohu říci, zda k nim skutečně dochází. Ale pokud mluvíme o filozofii rozvoje, uvažujeme takto: máme perimetr, který poskytuje chlapům, kteří dělají bezpečnost – tohle je hrad, zeď; a uvnitř perimetru si můžete dělat, co chcete. Je jasné, že existují uživatelé s možností pouze prohlížet a jsou uživatelé s možností vymazat adresář.

V závislosti na právech může být poškozením, které uživatelé mohou způsobit, myš nebo slon. Je jasné, že uživatel s plnými právy může dělat vůbec cokoli. Uživatel s omezenými právy může způsobit podstatně menší škody. Zejména nemůže rozbít systém.

In: – V chráněném perimetru se někdo pokusil vytvořit neočekávané protokoly pro server, aby server úplně zničil, a pokud budete mít štěstí, celý cluster... Přijde vám to někdy tak „dobré“?

MT: "Nikdy jsem o takových věcech neslyšel." Skutečnost, že tímto způsobem můžete srazit server, není žádným tajemstvím. Selhat uvnitř, být z protokolu, být oprávněným uživatelem, který může něco takového napsat do zprávy... Ve skutečnosti je to nemožné, protože to bude ještě ověřeno. Uživatelům, kteří si to nepřejí, je možné toto ověřování zakázat - pak je to jejich problém; oni si, zhruba řečeno, sami zničili zdi a můžete tam strčit slona, ​​který dupe... Ale obecně se můžete obléknout jako opravář, pojďte to vytáhnout!

In: – Díky za zprávu. Sergey (Yandex). V Mong je konstanta, která omezuje počet hlasujících členů v sadě replik, a tato konstanta je 7 (sedm). Proč je to konstanta? Proč to není nějaký parametr?

MT: – Máme sady replik se 40 uzly. Vždy existuje většina. Nevím kterou verzi...

In: – V Replica Set můžete provozovat nehlasující členy, ale hlasujících členů je maximálně 7. Jak můžeme v tomto případě přežít odstávku, když je naše Replica Set rozmístěna ve 3 datových centrech? Jedno datové centrum se může snadno vypnout a další stroj může vypadnout.

MT: – To už je trochu nad rámec zprávy. To je obecná otázka. Možná vám o tom povím později.

HighLoad++, Michail Tyulenev (MongoDB): Kauzální konzistence: od teorie k praxi

Nějaké inzeráty 🙂

Děkujeme, že s námi zůstáváte. Líbí se vám naše články? Chcete vidět více zajímavého obsahu? Podpořte nás objednávkou nebo doporučením přátelům, cloud VPS pro vývojáře od 4.99 $, jedinečný analog serverů základní úrovně, který jsme pro vás vymysleli: Celá pravda o VPS (KVM) E5-2697 v3 (6 jader) 10GB DDR4 480GB SSD 1Gbps od 19 $ nebo jak sdílet server? (k dispozici s RAID1 a RAID10, až 24 jader a až 40 GB DDR4).

Dell R730xd 2krát levnější v datovém centru Equinix Tier IV v Amsterdamu? Pouze zde 2 x Intel TetraDeca-Core Xeon 2 x E5-2697v3 2.6 GHz 14C 64 GB DDR4 4 x 960 GB SSD 1 Gbps 100 TV od 199 USD V Nizozemsku! Dell R420 – 2x E5-2430 2.2 GHz 6C 128 GB DDR3 2 x 960 GB SSD 1 Gb/s 100 TB – od 99 $! Číst o Jak budovat infrastrukturu corp. třídy s využitím serverů Dell R730xd E5-2650 v4 v hodnotě 9000 XNUMX eur za cent?

Zdroj: www.habr.com

Přidat komentář