Otázka: Jeden servisní server, jedna databáze, provoz: dotazujte na aktuální zůstatek uživatele, odečtěte 3 % z aktuálního zůstatku jako poplatek za zpracování
synchronizované zamknout DB Lock
Otázka: Dva servisní servery, jedna databáze, operace: dotazovat se na aktuální zůstatek uživatele, odečíst 3 % z aktuálního zůstatku jako poplatek za zpracování Distribuované zámky
Jaký typ distribuovaného zámku potřebujeme? Může zajistit, že v distribuovaném aplikačním clusteru může být stejná metoda vykonána pouze jedním vláknem na jednom stroji současně.
Pokud je tento zámek reentrantní (vyhněte se slepým zácpám)
Tento zámek je nejlepší jako blokovací zámek (zvažte, zda ho chcete podle potřeb vašeho podnikání)
Tento zámek je nejlepší být spravedlivý (zvažte, zda ho chcete podle potřeb firmy)
Jsou zde vysoce dostupné funkce zámku získávání a uvolnění
Výkon zámků pro získání a uvolnění je lepší
1. Distribuované zámky založené na databázích
Distribuované zámky založené na tabulkových implementacích
Když chceme metodu zamknout, spusťme následující SQL: vložte do methodLock(method_name,desc) hodnoty ('method_name','desc')
Protože jsme na method_name stanovili omezení jedinečnosti, pokud je do databáze současně odesláno více požadavků, databáze zajistí, že uspěje pouze jedna operace, můžeme předpokládat, že vlákno, které úspěšně získalo zámek metody, může vykonat obsah těla metody.
Když je metoda vykonána, pokud chcete zámek uvolnit, musíte spustit následující SQL: delete from methodLock, kde method_name ='method_name'
Tato jednoduchá implementace výše má následující problémy:
- Tento zámek závisí na dostupnosti databáze, což je jeden bod a způsobí, že podnikový systém bude nedostupný poté, co se databáze zasekne.
- Tento zámek nemá dobu vypršení platnosti a jakmile operace odemčení selže, záznam zámku zůstane v databázi a ostatní vlákna již nebudou schopna zámek získat.
- Tento zámek může být pouze neblokující, protože operace vložení dat přímo hlásí chybu po selhání vložení. Vlákna, která nezískají zámky, nevstoupí do fronty a budou muset operaci získání zámku spustit znovu, aby zámek znovu získala.
- Zámek není znovu vstupující a stejné vlákno nemůže zámek znovu získat, dokud není uvolněn. Protože data v datech už existují.
- Tento zámek je nespravedlivý a všechny vlákna čekající na zámek soupeří o zámek štěstím.
Samozřejmě můžeme výše uvedené problémy řešit i jinými způsoby.
- Je databáze jen jeden bod? Vytvoříte dvě databáze a data budou synchronizována v obou směrech. Jakmile se zavěsí, rychle přepněte na záložní knihovnu.
- Žádná doba expirace? Stačí pravidelně provádět naplánovaný úkol na vyčištění časových limitů v databázi.
- Neblokující? Dělejte dlouhou smyčku, dokud vložka neuspěje, a pak se vrátí úspěch.
- Ne-reentrant? Přidejte pole do tabulky databáze, kde se zaznamenávají informace o hostiteli a vláknech stroje, který právě má zámek, a příště, až ho dostanete, nejprve se dotazujte do databáze, pokud najdete informace o hostiteli a vláknech aktuálního stroje v databázi, můžete mu zámek přímo přiřadit.
- Nespravedlivé? Vytvořte další mezilehlou tabulku pro zaznamenání všech vláken čekajících na zámek a třídit je podle času vytvoření, přičemž pouze první vytvořené vlákno může zámek získat
Distribuované zámky založené na exkluzivních zámocích
Kromě přidávání a mazání záznamů v datové tabulce lze distribuované zámky implementovat také pomocí zámků, které jsou součástí dat.
Používáme také databázovou tabulku, kterou jsme právě vytvořili. Distribuované zámky lze implementovat prostřednictvím exkluzivních zámků v databázích. Engine InnoDB založený na MySQL může použít následující metody pro implementaci operací uzamčení:
Pokud přidáte pro aktualizaci po dotazovacím příkazu, databáze během dotazovacího procesu přidá exkluzivní zámek do databázové tabulky. Když je do záznamu přidán exkluzivní zámek, ostatní vlákna již nemohou přidat exkluzivní zámek do záznamu na tomto řádku.
Můžeme si myslet, že vlákno, které získá exkluzivní zámek, může získat distribuovaný zámek, a když je zámek získán, lze spustit obchodní logiku metody a poté ji odemknout pomocí následujících metod:
public void unlock(){ connection.commit(); }
via connection.commit(); operace k uvolnění zámku.
Tato metoda může účinně vyřešit výše zmíněné problémy týkající se nemožnosti uvolnit a zablokovat zámek.
Blokování zámků? Příkaz for update se vrátí ihned po úspěšném provedení a zůstává blokován, dokud neuspěje.
Služba po zámeku nefunguje, nelze ji uvolnit? Tímto způsobem databáze sama uvolní zámek poté, co služba přestane fungovat.
Přesto to přímo neřeší problém databázového jediného bodu, reentrance a spravedlivého uzamčení.
Shrnuto, jak využít databázi k implementaci distribuovaných zámků, které oba spoléhají na tabulku v databázi, jedním je zjistit, zda zámek existuje, na základě existence záznamů v tabulce, a druhým je implementovat distribuované zámky prostřednictvím exkluzivního zámku databáze.
Výhody distribuovaného uzamčení v databázích
Přímo s pomocí databáze je to snadno pochopitelné.
Nevýhody implementace distribuovaných zámků v databázích
Objeví se různé problémy a celé řešení se bude v procesu jejich řešení stále složitější.
Provoz databáze vyžaduje určité režie a je třeba zvážit i výkonnostní otázky.
2. Distribuované zámky založené na cache
Ve srovnání s databázovým řešením distribuovaného zamykaní bude implementace založená na cache výkonnostně lepší.
V současnosti existuje mnoho vyspělých produktů pro cache, včetně Redis, memcached a dalších. Zde vezmeme Redis jako příklad k analýze schématu využití cache k implementaci distribuovaných zámků.
Na internetu je mnoho souvisejících článků o implementaci distribuovaných zámků založených na Redis a hlavní metodou implementace je použití metody Jedis.setNX.
Existuje také několik problémů s výše uvedenou implementací:
1. Problém s jedním bodem.
2. Tento zámek nemá dobu vypršení, jakmile operace odemčení selže, způsobí, že záznam zámku bude neustále v redis a ostatní vlákna již zámek nezískají.
3. Tento zámek může být pouze neblokující a vrátí se přímo bez ohledu na úspěch či neúspěch.
4. Tento zámek není reentrantní, po získání zámku vláknem nemůže zámek znovu získat před jeho uvolněním, protože použitý klíč již v redis existuje. operace setNX již nelze vykonávat.
5. Tento zámek je nespravedlivý, všechna čekající vlákna zahajují operace setNX současně a šťastná vlákna mohou zámek získat.
Samozřejmě existují i způsoby, jak to vyřešit.
- V současnosti hlavní cache služby podporují nasazení clusterů pro řešení problémů jednoho bodu pomocí clusteringu.
- Žádná doba expirace? Metoda setExpire v redis podporuje příchozí dobu expirace a data jsou automaticky smazána po dosažení tohoto času.
- Neblokující? a zároveň opakovaně popravován.
- Není možné se znovu vrátit? Po získání zámku vláknem si uložte aktuální informace o hostiteli a vlákně a zkontrolujte, zda jste vlastníkem aktuálního zámku, než ho příště získáte.
- Nespravedlivé? Všechna čekající vlákna dejte do fronty před tím, než vlákno získá zámek, a poté ho získáte na principu první dovnitř, první ven.
Synchronizační politika redis clusteru trvá čas a je možné, že vlákno A po úspěšném nastavení NX získá zámek, ale tato hodnota nebyla aktualizována na serveru, kde vlákno B vykonává setNX, což způsobí problémy se souběžností.
Salvatore Sanfilippo, autor redis, navrhl algoritmus Redlock, který implementuje distribuovanou správu zámků (DLM) bezpečnější a spolehlivější než jeden uzel.
Algoritmus Redlock předpokládá, že existuje N uzlů redis nezávislých na sobě, obvykle nastavených na N=5, a těchto N uzlů běží na různých strojích, aby si zachovaly fyzickou nezávislost.
Kroky algoritmu jsou následující:
1. Klient získá aktuální čas v milisekundách. 2. Klient se snaží získat zámek N uzlů (každý uzel získá zámek stejným způsobem jako dříve zmíněný cache zámek) a N uzlů získá zámek se stejným klíčem a hodnotou. Klient musí nastavit časový limit přístupu k rozhraní a čas vypršení rozhraní musí být mnohem kratší než časový limit zámku, například čas automatického uvolnění zámku je 10 sekund, pak je časový limit rozhraní nastaven na přibližně 5–50 ms. To vám umožní co nejdříve vypršet čas při přístupu k uzlu Redis po jeho výpadku a snižuje běžné používání zámku. 3. Klient vypočítá, kolik času trvá získání zámku, odečtením času získaného v kroku 1 aktuálním časem; pouze když klient získá více než 3 uzly zámku a čas k získání zámku je kratší než čas vypršení zámku, klient získá distribuovaný zámek. 4. Čas klienta na získání zámku je časový limit nastavení minus čas potřebný k získání zámku vypočítaný v kroku 3. 5. Pokud klient nezíská zámek, smaže všechny zámky postupně. Použitím algoritmu Redlock lze zaručit, že distribuovaná služba zámku může fungovat i při zavěšení až 2 uzlů, což výrazně zlepšuje dostupnost oproti předchozímu zámku a cache locku databáze.
Nicméně distribuovaný expert napsal článek "Jak dělat distribuované zamykaní", který zpochybňoval správnost Redlocku.
Odborník uvedl, že při zvažování distribuovaných zámků je třeba zvážit dva aspekty: výkon a správnost.
Pokud používáte vysoce výkonný distribuovaný zámek a správnost není vyžadována, pak je použití cache zámku dostačující.
Pokud používáte vysoce spolehlivý distribuovaný zámek, musíte zvážit přísné otázky spolehlivosti. Redlock naopak nesplňuje správnou hodnotu. Proč ne? Odborníci uvádějí několik aspektů.
V současnosti mnoho programovacích jazyků používá virtuální stroje s funkcemi GC, v Full GC program přestane GC zpracovávat, někdy Full GC trvá dlouho a dokonce program má několik minut zpoždění, článek uvádí příklad HBase, HBase někdy GC na několik minut, což způsobí vypršení doby pronájmu. Například na obrázku níže klient 1 dostane zámek a chystá se zpracovat sdílený zdroj, a když se chystá zpracovat sdílený zdroj, nastává Full GC, dokud zámek nevyprší. Tímto způsobem klient 2 opět získá zámek a začne pracovat na sdíleném zdroji. Když klient 2 zpracovává, klient 1 dokončí plnou GC a začne zpracovávat sdílené zdroje, takže oba klienti zpracovávají sdílené zdroje.
Odborníci navrhli řešení, jak je znázorněno na obrázku níže, vypadá to takto: MVCC, přines token k zámku, token je koncept verze, pokaždé, když je operace zamčený dokončen, token se přidá. 1, přinese token při zpracování sdílených zdrojů, pouze specifikovaná verze tokenu může sdílet sdílený zdroj.
Pak odborník také uvedl, že algoritmus spoléhá na lokální čas a že Redis spoléhá na metodu getTimeOfDay pro získání času místo monotónních hodin při zpracování expirace klíče, což také vede k časovým nepřesnostem. Například v jednom scénáři mají dva klient 1 a klient 2 5 uzlů redis (A, B, C, D a E).
1. Klient 1 úspěšně získá zámek od A, B a C a získá časový limit sítě zámků od D a E. 2. Hodiny uzlu C jsou nepřesné, což způsobuje časový limit zámku. 3. klient 2 úspěšně získá zámek od C, D a E a získá timeout sítě zámků od A a B. 4. Tímto způsobem mají klient 1 i klient 2 zámek. Shrnuté dva body, které odborníci říkají o nedostupnosti Redlocku:
1. GC a další scénáře mohou nastat kdykoli, což způsobí, že klient získá zámek, a časový limit zpracování způsobí, že zámek získá jiný klient. Odborníci také nabídli řešení pro použití samopřirůstajících tokenů. 2. Algoritmus spoléhá na místní čas a hodiny budou nepřesné, což vede k tomu, že dva klienti získají zámky současně. Odborníci tedy dospěli k závěru, že Redlock může normálně fungovat pouze v omezeném síťovém zpoždění, omezeném přerušení programu a omezeném rozsahu chyb hodin, ale hranice těchto tří scénářů nelze potvrdit, proto odborníci Redlock nedoporučují. Pro scénáře s vysokými požadavky na správnost odborníci doporučují Zookeeper, o kterém budeme později diskutovat s použitím Zookeeperu jako distribuovaného zámku.
Odpověď autora knihy Redis
Autor Redis reagoval napsáním blogu poté, co viděl článek odborníka. Autor odborníkovi zdvořile poděkoval a poté vyjádřil svůj nesouhlas s jeho názorem.
Diskuse autora REDIS o použití tokenů k řešení problému timeoutu lze shrnout do následujících pěti bodů:
Bod 1, použití distribuovaných zámků je obecně v tom, že nemáte jiný způsob, jak ovládat sdílené zdroje, odborníci používají tokeny k zajištění zpracování sdílených zdrojů, pak není potřeba distribuovaných zámků. Bod 2: Pro generování tokenů, aby byla zajištěna spolehlivost tokenů získaných různými klienty, služba generující tokeny stále potřebuje distribuované zámky pro zajištění spolehlivosti služby. Bod 3, pokud jde o způsob, jakým odborníci říkají o samoinkrementujících tokenech, autor redis věří, že je to zcela zbytečné, každý klient může generovat unikátní UUID jako token a nastavit sdílený zdroj do stavu, který může zpracovat pouze klient s UUID, takže ostatní klienti nemohou sdílet zdroj zpracovávat, dokud klient, který zámek získá, zámek neuvolní. Jak je znázorněno na obrázku výše, pokud klient tokenu 34 během zápisu odešle GC a způsobí vypršení zámku, může jiný klient získat zámek tokenu 35 a začít znovu zapisovat, což vede ke konfliktu zámku. Proto nelze pořadí tokenů kombinovat se sdílenými zdroji. Bod 5: autor redis věří, že ve většině scénářů se distribuované zámky používají k řešení problémů s aktualizacemi v netransakčních scénářích. Autor by měl myslet na to, že existují situace, kdy je obtížné tokeny kombinovat pro zpracování sdílených zdrojů, takže musíte spoléhat na zámky k zajištění a zpracování zdrojů. Další problém s hodinami, o kterém odborníci mluví, autory Redis také podávají vysvětlení. Pokud je čas potřebný k získání zámku příliš dlouhý a přesahuje výchozí časový limit zámku, klient v tuto chvíli zámek získat nemůže a odborníci nebudou navrhovat žádné příklady.
Osobní pocity
Prvním problémem, který shrnuji, je, že poté, co klient získá distribuovaný zámek, může být zámek uvolněn po uplynutí času během zpracování klientem. Dříve, když se mluvilo o timeoutu nastaveném zámkem databáze na 2 minuty, pokud úkol zabere zamčení příkazu déle než 2 minuty, druhé obchodní centrum může tento zámek získat, takže obě obchodní centra mohou zpracovat stejný příkaz současně. Za normálních okolností je úkol zpracován během několika sekund, ale někdy je časový limit nastavený připojením k RPC požadavku příliš dlouhý a v úkolu je více takových požadavků, takže je pravděpodobné, že čas automatického odemykání bude překročen. Pokud píšeme v javě, může být uprostřed Full GC, takže po odemčení zámku po timeoutu klient nemůže zámek vnímat, což je velmi vážná věc. Nemyslím si, že je to problém samotného zámku, pokud má jakýkoli výše zmíněný distribuovaný zámek vlastnosti uvolnění časového limitu, takový problém nastane. Pokud použijete funkci timeoutu zámku, klient musí časový limit nastavit a podle toho jednat, místo aby pokračoval ve zpracování sdíleného zdroje. Redlockův algoritmus vrací čas zámku, který klient může obsadit poté, co klient zámek získá, a klient musí tento čas zpracovat, aby úkol po uplynutí této doby zastavil.
Druhým problémem je, že distribuovaní experti Redlocku nerozumí. Klíčovou vlastností Redlocku je, že čas potřebný k získání zámku je celkový čas, který zámek automaticky přejde na časový limit minus čas potřebný k jeho získání, takže čas potřebný klientem ke zpracování je relativní, bez ohledu na místní čas.
Z tohoto pohledu lze správnost Redlocku dobře zaručit. Při pečlivé analýze Redlocku je hlavní vlastností Redlocku vyšší spolehlivost, což je v některých situacích důležitá vlastnost. Ale myslím, že Redlock utratil příliš mnoho peněz za dosažení spolehlivosti.
- Nejprve musí být nasazeno 5 uzlů, aby byl Redlock spolehlivější.
- Pak musíte požádat o 5 uzlů, abyste získali zámek, a metodou Future můžete nejprve požádat o 5 uzlů současně a pak získat výsledek odpovědi, což může zkrátit dobu odezvy, ale stále to trvá déle než jednouzlový redisový zámek.
- Protože je třeba získat více než 3 z 5 uzlů, může dojít ke konfliktu zámků, tedy že všichni získali 1–2 zámky, a v důsledku toho nikdo nemůže zámek získat, tento problém autor Redis využívá podstatu algoritmu raft, skrze náhodnou kolizi lze konfliktní dobu výrazně zkrátit, ale tomuto problému nelze příliš dobře předejít, zvláště když je zámek získán poprvé, takže časové náklady na jeho získání rostou.
- Pokud jsou 2 z 5 uzlů mimo provoz, dostupnost zámku se výrazně sníží, nejprve musíte počkat, až výsledky těchto dvou uzlů vyprší čas, než se vrátíte, a jsou jen 3 uzly, a klient musí získat zámky všech 3 uzlů, aby měl zámek, což je také obtížnější.
- Pokud existuje síťová partition, může nastat situace, kdy klient nikdy nebude schopen zámek získat.
Po analýze tolika důvodů si myslím, že nejkritičtějším bodem problému Redlocku je, že Redlock vyžaduje, aby klienti zajistili konzistenci zápisů, a backendových 5 uzlů je zcela nezávislých a všichni klienti musí provozovat těchto 5 uzlů. Pokud je leader mezi 5 uzly, klient může synchronizovat data leadera, pokud klient získá zámek od leadera, takže nedojde k problémům jako partitioning, timeouty a konflikty. Proto, aby byla zajištěna správnost distribuovaných zámků, myslím, že použití distribuované koordinační služby s výraznou konzistencí může problém lépe vyřešit.
Znovu vyvstává otázka, jak dlouho bych měl nastavit dobu expirace? Nastavení doby pro zneplatnění je příliš krátké a zámek se automaticky uvolní před vykonáním metody, což může vést ke problémům se souběžností. Pokud to trvá příliš dlouho, ostatní vlákna, která se zámkem dostanou, budou muset čekat dlouho.
Tento problém existuje i při použití databází k implementaci distribuovaných zámků.
Současný běžný přístup k tomuto problému je nastavit krátký čas vypršení času pro každý získaný zámek a zahájit vlákno, které obnovuje čas vypršení zámku pokaždé, když se blíží k vypršení času. Ukončete toto vlákno současně s uvolněním zámku. Například redisson, oficiální komponenta distribuovaného zámku v redis, používá toto řešení.
Výhody využití cache k implementaci distribuovaných zámků Dobrý výkon.
Nevýhody použití cache k implementaci distribuovaných zámků Implementace je příliš zodpovědná, je příliš mnoho faktorů k zohlednění.
Distribuované zámky založené na implementaci Zookeeperu
Distribuované zámky založené na dočasně uspořádaných uzlech Zookeeperu.
Obecná myšlenka je, že když každý klient uzamkne metodu, vygeneruje se unikátní okamžitě uspořádaný uzel v adresáři určeného uzlu odpovídajícího metodě na zookeeperu. Způsob, jak zjistit, zda chcete zámek získat, je jednoduchý – stačí určit ten s nejmenším sériovým číslem v uspořádaném uzlu. Když je zámek uvolněn, jednoduše smažte okamžitý uzel. Zároveň se může vyhnout problému zablokování způsobeného výpadky služby, které nelze uvolnit.
Uvidíme, jestli Zookeeper dokáže vyřešit dříve zmíněné problémy.
- Zámek se nepustí? Použití Zookeeperu může efektivně vyřešit problém neuvolňování zámků, protože při vytváření zámku klient vytvoří dočasný uzel v ZK, a jakmile klient zámek získá a náhle ho zavěsí (spojení relace je přerušeno), dočasný uzel bude automaticky smazán. Ostatní klienti mohou zámek získat znovu.
- Zámky, které neblokují? Jakmile se uzel změní, Zookeeper klienta upozorní a klient může zkontrolovat, zda vytvořený uzel je nejmenším ordinálním číslem ze všech uzlů.
- Nemůžete znovu vstoupit? Když klient vytvoří uzel, přímo zapíše informace o hostiteli a vláknech aktuálního klienta na uzel, a příště, když chcete získat zámek, můžete je porovnat s daty v aktuálně nejmenším uzlu. Pokud jsou informace stejné jako vaše, můžete zámek získat přímo, a pokud je jiný, vytvořit dočasný sekvenční uzel, který se zapojí do fronty.
Otázka se znovu vyvstává – víme, že Zookeeper musí být nasazen v clusterech, budou problémy se synchronizací dat jako u clusterů Redis?
Zookeeper je distribuovaná komponenta, která zaručuje slabou konzistenci, tedy konečnou konzistenci.
Zookeeper používá protokol pro synchronizaci dat nazvaný Quorum Based Protocol. Pokud je v clusteru Zookeeper N serverů Zookeeper (N je obvykle liché, 3 splňují spolehlivost dat a mají vysoký výkon čtení a zápisu, a 5 má nejlepší rovnováhu mezi spolehlivostí dat a výkonem čtení a zápisu), pak je nejprve synchronizována zápisová operace uživatele na N/2 + 1 servery a poté vrácena uživateli, což uživatele vyzve k úspěšnému zápisu. Protokol pro synchronizaci dat založený na protokolu Quorum Basis určuje konzistenci síly, kterou Zookeeper dokáže podporovat.
V distribuovaném prostředí je úložiště dat, které dosahuje silné konzistence, prakticky neexistující a vyžaduje, aby všechny uzly byly při aktualizaci dat jednoho uzlu aktualizovány synchronně. Tato strategie synchronizace se objevuje v databázi master-slave synchronní replikace. Tato synchronizační strategie však má příliš velký dopad na výkon zápisu a v praxi se vyskytuje jen zřídka. Protože Zookeeper zapisuje N/2+1 uzlů synchronně a N/2 uzly nejsou synchronně aktualizovány, Zookeeper není silně konzistentní.
Aktualizace dat uživatelem nezaručuje, že další čtení přečtou aktualizovanou hodnotu, ale nakonec vykazuje konzistenci. Obětování konzistence neznamená úplné ignorování konzistence dat, jinak jsou data chaotická, takže bez ohledu na to, jak vysoká je dostupnost systému nebo jak dobré je rozložení, nemá to žádnou hodnotu. Obětování konzistence znamená, že silná konzistence v relačních databázích už není potřeba, ale pokud systém dokáže dosáhnout konečné konzistence.
Otázka na jeden bod? Použití Zookeeperu může efektivně vyřešit problém jednoho bodu, ZK je nasazen v clusterech, pokud přežije více než polovina strojů v clusteru, může být služba poskytována i vnějšímu světu.
Problémy se spravedlností? Použití Zookeeperu může vyřešit problém spravedlivých zámků, dočasné uzly vytvořené klientem v ZK jsou uspořádané a pokaždé, když je zámek uvolněn, může ZK upozornit nejmenší uzel, aby zámek získal, což zajišťuje spravedlnost.
Otázka se znovu vyvstává – víme, že Zookeeper musí být nasazen v clusterech, budou problémy se synchronizací dat jako u clusterů Redis?
Zookeeper je distribuovaná komponenta, která zaručuje slabou konzistenci, tedy konečnou konzistenci.
Zookeeper používá protokol pro synchronizaci dat nazvaný Quorum Based Protocol. Pokud je v clusteru Zookeeper N serverů Zookeeper (N je obvykle liché, 3 splňují spolehlivost dat a mají vysoký výkon čtení a zápisu, a 5 má nejlepší rovnováhu mezi spolehlivostí dat a výkonem čtení a zápisu), pak je nejprve synchronizována zápisová operace uživatele na N/2 + 1 servery a poté vrácena uživateli, což uživatele vyzve k úspěšnému zápisu. Protokol pro synchronizaci dat založený na protokolu Quorum Basis určuje konzistenci síly, kterou Zookeeper dokáže podporovat.
V distribuovaném prostředí je úložiště dat, které dosahuje silné konzistence, prakticky neexistující a vyžaduje, aby všechny uzly byly při aktualizaci dat jednoho uzlu aktualizovány synchronně. Tato strategie synchronizace se objevuje v databázi master-slave synchronní replikace. Tato synchronizační strategie však má příliš velký dopad na výkon zápisu a v praxi se vyskytuje jen zřídka. Protože Zookeeper zapisuje N/2+1 uzlů synchronně a N/2 uzly nejsou synchronně aktualizovány, Zookeeper není silně konzistentní.
Aktualizace dat uživatelem nezaručuje, že další čtení přečtou aktualizovanou hodnotu, ale nakonec vykazuje konzistenci. Obětování konzistence neznamená úplné ignorování konzistence dat, jinak jsou data chaotická, takže bez ohledu na to, jak vysoká je dostupnost systému nebo jak dobré je rozložení, nemá to žádnou hodnotu. Obětování konzistence znamená, že silná konzistence v relačních databázích už není potřeba, ale pokud systém dokáže dosáhnout konečné konzistence.
Zda Zookeeper splňuje kauzální konzistenci, závisí na tom, jak je klient naprogramován.
Praktiky, které nesplňují kauzální konzistenci
- Proces A zapíše kus dat do /z Zookeeperu a úspěšně vrátí
- Proces A informuje proces B, že A upravil data /z
- B čte data z /z Zookeepera
- Protože server Zookeepera připojený k B nemusí být aktualizován o A-ova psaná data, B nebude schopen číst A-ova zapsaná data
Praktiky, které splňují kauzální konzistenci
- Proces B naslouchá změnám dat v /z na Zookeeperu
- Proces A zapíše kus dat do /z Zookeeperu a než se úspěšně vrátí, musí Zookeeper zavolat posluchači registrovanému na /z a vedoucí upozorní B na změnu dat
- Po odpovědi na reakci na událost procesu B vezme změněná data, takže B určitě získá změněnou hodnotu
- Kauzální konzistence zde označuje kauzální konzistenci mezi vedoucím a B, tedy vedoucí oznamuje data o změně
Druhý mechanismus poslechu událostí je také metodou, která by měla být použita pro správné programování Zookeeperu, takže Zookeeper by měl splňovat kauzální konzistenci
Proto při implementaci distribuovaných zámků založených na Zookeeperu bychom měli použít praxi uspokojování kauzální konzistence, tedy že vlákna čekající na zámek naslouchají změnám v zámku Zookeeperu a když je zámek uvolněn, Zookeeper upozorní čekající vlákno, které splňuje podmínky spravedlivého zámku.
Můžete přímo použít klienta třetí strany Zookeeper, který zapouzdřuje službu reentrantního zámku.
Distribuované zámky implementované pomocí ZK přesně odpovídají tomu, co jsme od distribuovaného zámku očekávali na začátku tohoto článku. Není tomu však a distribuovaný zámek implementovaný Zookeeperem má ve skutečnosti nevýhodu, totiž výkon nemusí být tak vysoký jako u cacheovací služby. Protože pokaždé při vytváření a uvolnění zámku musí být dynamicky vytvářeny a zničeny okamžité uzly, aby byla funkce zámku realizována. Vytváření a mazání uzlů v ZK lze provádět pouze přes leader server a poté jsou data sdílena se všemi follower stroji.
Výhody použití Zookeeperu k implementaci distribuovaných zámků Efektivně řeší problémy s jedním bodem, problémy bez návratu, neblokování a selhání při uvolnění zámku. Je to relativně jednoduché na implementaci.
Nevýhody použití Zookeeperu k implementaci distribuovaných zámků Výkon není tak dobrý jako při použití cache pro implementaci distribuovaných zámků. Je vyžadováno pochopení principů ZK.
Srovnání tří možností
Z pohledu snadného pochopení (od nízké po vysokou) Database > Cache > Zookeeper
Z pohledu složitosti implementace (od nízké po vysokou) Zookeeper > cache > databází
Z hlediska výkonu (od vysokého po nízké) Cacheování > Zookeeper >= databáze
Z hlediska spolehlivosti (od vysokého po nízké) Zookeeper > cache > databází
|