V rubrice Scale-out data se na cloudsvet.cz zajímáme o object storage, Big Data mechanismy a NoSQL. To všechno jsou distribuované systémy a o těch je CAP teorém.
Od Scale-up ke Scale-out
V datové vrstvě světu dlouho vládnou systémy vertikálně škálující: Chcete víc? Přidejte systému paměť, CPU, … Přestože už dost let mají vnitřní paralelismus (podpora více vláken, storage pole rozkládá své úkony přes více disků apod.), často jsou stále řešeny principem centrální jednotky. Jde pak o jedno aktivní storage pole, jeden velký relační databázový server, jeden NAS server. Vertikální škálovatelnost (scale-up) je ale drahá. Vezměme například zvyšování počtu CPU v jednom systému. Z 1P na 2P systém není problém. Ale bude 4P systém stejně drahý jako dvojice 2P? Asi ne. A co teprve třeba takový 8P nebo 16P? Vyjde 16P monstrum na stejné peníze jako 8x komoditní 2P o stejné celkové kapacitě? S roustoucími potřebami neroste cena lineárně a v nějaký okamžik už scale-up ani není technicky proveditelný. Proto firmy jako Netflix (a Facebook, Google, Amazon, Twitter, Box, Dropbox, Spotify, …) už dávno přešly ze scale-up na scale-out, tedy z relační databáze na NoSQL, z blokové a souborové storage na object store, z klasických prostředků chroupání dat na Hadoop. Designové a konfigurační volby těchto systémů jsou omezeny prostorem definovaným CAP teorémem.
CAP teorém zjednodušeně
Na konci tisíciletí formuloval Eric Brewer CAP teorém, základní omezení distribuovaných systémů.
Consistency – originál mluví o konzistentním dodržení pořadí operací na všech uzlech. Přeformulováno populárně naučně je to o tom, že v každé milisekundě dostanete vždy správnou odpověď. Nestane se, že v Praze provedete aktualizaci, systém vrátí “OK, zapsáno” a v ten stejný okamžik si někdo v Mexiku přečte starší hodnotu.
Availability – všechny funkční nody jsou schopny přijímat požadavky. Uzel, kterému vypadla síťová konektivita k ostatním JE funkční a musí tedy odpovídat.
Partitioning tolerance – systém musí být schopen se vypořádat se situací, kdy se některé nody vzájemně nevidí.
Teorém říká, že není možné dosáhnout všech tří vlastností současně. Nicméně pozor, zatímco C a A je vaše volba, P u distribuovaného systému prostě je. Pokud nejste schopni zabránit ztrátě kontektivity mezi některými uzly (a to asi nejste), potřebujete, aby měl systém vlastnost P (tedy nehavaroval a byl schopen funkčnosti). Máme-li tedy “vybráno” P, můžeme mít buď C a nebo A. Příklad na třech uzlech je jednoduchý. Pokud jeden z nich nevidí ostatní dva, co se bude dít? Pokud chcete A, tedy všechny tři nadále přijímají požadavky (systém nepociťuje žádnou havárii či ztrátu výkonu), je jasné, že vzájemně nekomunikující uzly dříve či později provedou nekonzistentní operace, takže nemáte C. Zajistit C můžete tak, že se jedna odtržená skupina vypne – v našem případě bez kvóra to bude ten osamocený uzel. Tím jsme porušili A. To jsou omezení daná CAP teorémem – nicméně jak uvidíme později, nemusí se rozhodovat takto za celý systém, ale vlastnosti můžeme volit více granulárně.
Designové volby aneb typy systémů
Možná postavíte takový systém, ve kterém ke ztrátě komunikace nikdy nedojde. V praxi to takhle může vypadat uvnitř velkého business critical serveru. Klasické relační databázové systémy se obvykle označují jako CA a běží na jediném serveru (možná mají řešení, které dokáže systém rychle naklonovat v případě jeho havárie například udržováním dokonalé repliky – nicméně systém je ve skutečnosti aktivní pouze na jednom stroji…protože nemá P vlastnosti).
Scale-out systémy potřebují podporu P, jinak jsou k ničemu. Jedna rodina tedy bude postavena na AP principech. Typickým příkladem je třeba Swift objektová storage a řada NoSQL systémů jako je Cassandra, Voldemort, CouchDB nebo Dynamo. V případě roztržení přijímají všechny uzly dále požadavky a vznikají tak nekonzistence. Po obnovení spojení tak musí mít dobrý AP systém schopnost provést merge a případné konflikty vyřešit nejlépe sám (třeba ve stylu novější vyhrává nebo uložením obou verzí – už jste někdy v Evernote provedli změnu dokumentu offline v počítači i na tabletu?)
CP systém v případě svého roztržení bude zajišťovat konzistenci. To v praxi znamená, že některé nody přestanou řešit požadavky uživatelů (tedy porušení principů A). Důležitou vlastností CP systému je schopnost zvolit kdo v případě roztržení bude obsluhovat klienty a kdo se nuceně odmlčí. Ke slovu přichází varianty jako externí pozorovatel (kvórum), větší zbytek roztrženého clusteru (typicky se právě CP systémy staví v lichém počtu uzlů), ten kousek, který má dříve zvoleného mastera apod. CP chování má ve výchozím stavu třeba CEPH storage, MongoDB, Redis, Memcache nebo HBase.
PACELC – nejhorší název pro nejlepší rozšíření CAP
V rámci CAP teorému se zanedbává jedna docela podstatná věc – latence. Podle speciální teorie relativity se žádná informace nemůže šířit rychleji, než rychlostí světla. Přidejte nějakou (nemalou) režii a je jasné, že udržovat konzistenci v clusteru rozprostřeném přes planetu má masivní dopady na výkon (proto se třeba synchronní replikace storage pole nedoporučuje pro větší vzdálenosti). Daniel Abadi tak rozšiřuje CAP o popis strategie v okamžiku, kdy roztržení nenastalo. Říká tedy, že v případě Partitioningu volí systém buď Availability nebo Consistency. Else (pokud je cluster vcelku, tedy v normálu) upřednostňuje Latency nebo Consistency. Příklad optimalizace pro nízkou latenci jsou řešení postavená na Eventuální konzistenci – výkonná, masivně škálující a levná na hardware (a licence). Za konzistenci zaplatíte daň – na výstupu se musí nody shodnout, tedy před odpovědí se poradit, tedy vyměnit si informace maximálně rychlostí světla a to přináší latenci.
Nic není černobíle aneb odstřižený bankomat
Moderní bankomat umožňuje dvě operace – vkládat a vybírat peníze. Jde o distribuovaný systém – prevence vyběru do záporu spočívá v konzultaci s jinými, kteří znají stav vašeho konta (bankovní systém). Co dělat, když bankomatu vypadne síťové spojení? Má být systém CP nebo AP?
CP je v zásadě vypnutí bankomatu. Jedině tak lze zajistit, že někdo, kdo na účtu nemá peníze, nebude schopen peníze vybrat. Znamená to ale také nefunkční bankomat, tedy ztrátu zisku a naštvání zákazníků.
AP řešení by dovolovalo bankomatu dál pracovat plně funkčně s tím, že loguje všechny transakce a zpětně je předá dál v okamžiku, kdy se síťové spojení obnoví. Bankomat funguje, zákazníci jsou spokojeni, žádné obchodní příležitosti nejsou ohroženy. Nicméně někdo, kdo nemá peníze, si je i přes to může vybrat – to po něm sice je možné vymáhat a nechat ho zaplatit úrok, ale je to neschválený úvěr a riziko. Pokud vás teď napadlo, že by přece stav všech kont mohl být nahraný v bankomatu, nic moc to neřeší. Pomineme-li očividné potíže (příliš mnoho často se měnících dat, náročnost na konektivitu a koordinaci, bezpečnostní otazníky), stačí najít několik offline bankomatů a ze všech vybrat současně. AP systém se nemůže domluvit a přijít na to, to je dané CAP teorémem.
Jak byste situaci řešili vy? Moderní systémy umožňují namíchat CP a AP vlastnosti s větší granularitou a tak fungují většinou i bankomaty. Vklad hotovosti není větší problém, pokud vím, že síťové spojení se obnoví vždy v řádu pár hodin. Klidně si zákazníci mohou vložit peníze, na účtu se to holt projeví až po nějaké době, ale o nic nemůžou přijít (je to bezpečné). A výběry? Zvážíte riziko neoprávněného výběru a pravděpodobně dojdete k závěru, že je výhodnější menší výběry povolit i offline (tedy udržet funkčnost a nepřijít o poplatky za výběr apod.), ale od určité částky, třeba 2000 Kč, takovou operaci neumožnit. Tedy chovat se AP způsobem pro některé operace, ale jako CP pro jiné. Právě takové možnosti nabízí moderní NoSQL a object storage systémy – jejich chování lze často velmi detailně nastavit.