O přesunu z Redis do Redis-cluster

O přesunu z Redis do Redis-cluster

Když přijdeme na produkt, který se vyvíjí více než deset let, není vůbec překvapivé, že v něm najdeme zastaralé technologie. Ale co když za šest měsíců budete muset držet zátěž 10krát vyšší a náklady na pády stoupnou stokrát? V tomto případě potřebujete skvělého Highload Engineera. Ale v nepřítomnosti pokojské mě pověřili řešením problému. V první části článku vám prozradím, jak jsme přešli z Redis na Redis-cluster a v druhé části poradím, jak cluster začít používat a na co si dát při jeho používání pozor.

Volba technologie

Je to tak špatné? samostatný Redis (standalone redis) v konfiguraci 1 master a N slave? Proč tomu říkám zastaralá technologie?

Ne, Redis není tak špatný... Nicméně jsou zde některé nedostatky, které nelze ignorovat.

  • Za prvé, Redis nepodporuje mechanismy obnovy po havárii po hlavním selhání. K vyřešení tohoto problému jsme použili konfiguraci s automatickým převodem VIP na nového mastera, změnou role jednoho z slave a přepnutím zbytku. Tento mechanismus fungoval, ale nedalo se nazvat spolehlivým řešením. Zaprvé došlo k falešným poplachům, zadruhé byl jednorázový a po obsluze bylo nutné pružinu nabít ručně.

  • Za druhé, mít pouze jednoho mistra vedlo k problému shardingu. Museli jsme vytvořit několik nezávislých klastrů „1 master a N slave“, pak ručně distribuovat databáze mezi tyto stroje a doufat, že zítra jedna z databází nenabobtná natolik, že by se musela přesunout do samostatné instance.

Jaké jsou možnosti?

  • Nejdražším a nejbohatším řešením je Redis-Enterprise. Jedná se o krabicové řešení s plnou technickou podporou. Přesto, že po technické stránce vypadá ideálně, z ideologických důvodů nám nevyhovoval.
  • Redis-cluster. Po vybalení je podpora pro master failover a sharding. Rozhraní se téměř neliší od běžné verze. Vypadá to slibně, o úskalích si povíme později.
  • Tarantool, Memcache, Aerospike a další. Všechny tyto nástroje dělají v podstatě totéž. Ale každý má své vlastní nedostatky. Rozhodli jsme se nedávat všechna vejce do jednoho košíku. Pro jiné úkoly používáme Memcache a Tarantool a při pohledu dopředu řeknu, že v naší praxi s nimi bylo více problémů.

Specifika použití

Pojďme se podívat na to, jaké problémy jsme s Redisem historicky řešili a jakou funkcionalitu jsme používali:

  • Cache před požadavky na vzdálené služby jako 2GIS | Golang

    GET SET MGET MSET "SELECT DB"

  • Cache před MYSQL | PHP

    GET SET MGET MSET SCAN "KEY BY VZOR" "VYBRAT DB"

  • Hlavní úložiště pro službu práce s relacemi a souřadnicemi řidiče | Golang

    GET SET MGET MSET "SELECT DB" "ADD GEO KEY" "GET GEO KEY" SKENOVÁNÍ

Jak vidíte, žádná vyšší matematika. Jaká je tedy obtížnost? Podívejme se na každou metodu zvlášť.

metoda
popis
Vlastnosti Redis-clusteru
rozhodnutí

ZÍSKEJTE SET
Klíč pro zápis/čtení

MGET MSET
Zápis/čtení více klíčů
Klíče budou na různých uzlech. Hotové knihovny mohou provádět více operací pouze v rámci jednoho uzlu
Nahraďte MGET kanálem operací N GET

VYBERTE DB
Vyberte základnu, se kterou budeme pracovat
Nepodporuje více databází
Dejte vše do jedné databáze. Přidejte předpony ke klíčům

SCAN
Projděte všechny klíče v databázi
Vzhledem k tomu, že máme jednu databázi, je procházení všech klíčů v clusteru příliš drahé
Udržujte invariant v rámci jednoho klíče a proveďte HSCAN na tomto klíči. Nebo úplně odmítnout

GEO
Operace s geoklíčem
Geoklíč není rozbitý

KLÍČ PODLE VZORU
Hledání klíče podle vzoru
Protože máme jednu databázi, budeme hledat napříč všemi klíči v clusteru. Příliš drahé
Odmítněte nebo ponechte invariant, jako v případě SCAN

Redis vs Redis-cluster

Co při přechodu na cluster ztrácíme a co získáváme?

  • Nevýhody: ztrácíme funkčnost několika databází.
    • Pokud chceme ukládat logicky nesouvisející data do jednoho shluku, budeme si muset udělat berličky v podobě prefixů.
    • Ztratíme všechny „základní“ operace, jako je SCAN, DBSIZE, CLEAR DB atd.
    • Implementace více operací se stala mnohem obtížnější, protože může vyžadovat přístup k několika uzlům.
  • Doplňky:
    • Odolnost proti chybám ve formě master failover.
    • Sharding na straně Redis.
    • Přenos dat mezi uzly atomicky a bez prostojů.
    • Přidejte a přerozdělte kapacitu a zatížení bez prostojů.

Došel bych k závěru, že pokud nepotřebujete poskytovat vysokou úroveň odolnosti proti chybám, pak se přechod do clusteru nevyplatí, protože to může být netriviální úkol. Pokud si ale zpočátku vybíráte mezi samostatnou verzí a clusterovou verzí, pak byste měli zvolit cluster, protože není o nic horší a navíc vás zbaví některých bolestí hlavy

Příprava na přesun

Začněme požadavky na stěhování:

  • Mělo by to být bezproblémové. Úplné zastavení provozu na 5 minut nám nevyhovuje.
  • Mělo by to být co nejbezpečnější a postupné. Chci mít nad situací určitou kontrolu. Nechceme vyhodit všechno najednou a modlit se za tlačítko vrácení.
  • Minimální ztráta dat při přesunu. Chápeme, že bude velmi obtížné se atomicky přesouvat, takže umožňujeme určitou desynchronizaci mezi daty v běžném a clusterovém Redis.

Údržba clusteru

Těsně před přesunem bychom se měli zamyslet nad tím, zda můžeme cluster podpořit:

  • Grafy. Používáme Prometheus a Grafana ke grafu zatížení CPU, využití paměti, počtu klientů, počtu operací GET, SET, AUTH atd.
  • Odbornost. Představte si, že zítra budete mít pod svou odpovědností obrovský shluk. Pokud se rozbije, nikdo kromě vás to nemůže opravit. Pokud začne zpomalovat, všichni se rozběhnou proti vám. Pokud potřebujete přidat zdroje nebo přerozdělit zátěž, vraťte se k vám. Aby ve 25 nezešedly, je vhodné tyto případy zajistit a předem si ověřit, jak se bude technologie chovat při určitých akcích. Promluvme si o tom podrobněji v sekci „Odbornost“.
  • Monitorování a upozornění. Když se cluster rozpadne, chcete být první, kdo se o tom dozví. Zde jsme se omezili na upozornění, že všechny uzly vracejí stejné informace o stavu clusteru (ano, děje se to jinak). A další problémy lze rychleji zaznamenat pomocí upozornění z klientských služeb Redis.

Přemístění

Jak se budeme pohybovat:

  • Nejprve je potřeba připravit knihovnu pro práci s clusterem. Jako základ pro verzi Go jsme vzali go-redis a trochu jsme ho pozměnili, aby nám vyhovoval. Implementovali jsme Multi-methods prostřednictvím potrubí a také jsme mírně upravili pravidla pro opakování požadavků. Verze PHP měla více problémů, ale nakonec jsme se usadili na php-redis. Nedávno zavedli podporu clusteru a podle nás to vypadá dobře.
  • Dále je potřeba nasadit samotný cluster. To se provádí doslova ve dvou příkazech založených na konfiguračním souboru. O nastavení se budeme podrobněji bavit níže.
  • Pro postupný přesun používáme suchý režim. Vzhledem k tomu, že máme dvě verze knihovny se stejným rozhraním (jedna pro běžnou verzi, druhá pro cluster), nic nestojí vytvoření wrapperu, který bude pracovat se samostatnou verzí a paralelně duplikuje všechny požadavky do clusteru, porovnejte odpovědi a zapište nesrovnalosti do protokolů (v našem případě v NewRelic). I když se tedy verze clusteru během zavádění rozpadne, naše výroba nebude ovlivněna.
  • Po spuštění clusteru v suchém režimu se můžeme v klidu podívat na graf nesrovnalostí v odezvách. Pokud se chybovost pomalu, ale jistě pohybuje směrem k nějaké malé konstantě, pak je vše v pořádku. Proč stále existují nesrovnalosti? Protože k záznamu v samostatné verzi dochází o něco dříve než v clusteru a díky mikrolagu se mohou data rozcházet. Nezbývá než se podívat na záznamy o nesrovnalostech, a pokud jsou všechny vysvětleny neatomičností záznamu, pak můžeme pokračovat.
  • Nyní můžete přepnout suchý režim v opačném směru. Budeme zapisovat a číst z clusteru a duplikovat jej do samostatné verze. Proč? Během příštího týdne bych rád sledoval práci klastru. Pokud se náhle ukáže, že při špičkové zátěži dochází k problémům, nebo jsme s něčím nepočítali, vždy máme nouzový návrat ke starému kódu a aktuálním datům díky suchému režimu.
  • Zbývá pouze deaktivovat suchý režim a demontovat samostatnou verzi.

Odbornost

Nejprve krátce o návrhu clusteru.

Za prvé, Redis je obchod s páry klíč-hodnota. Jako klíče se používají libovolné řetězce. Jako hodnoty lze použít čísla, řetězce a celé struktury. Těch druhých je velké množství, ale pro pochopení obecné struktury to pro nás není důležité.
Další úrovní abstrakce po klíčích jsou sloty (SLOTS). Každý klíč patří do jednoho z 16 383 slotů. Uvnitř každého slotu může být libovolný počet klíčů. Všechny klíče jsou tedy rozděleny do 16 383 disjunktních sad.
O přesunu z Redis do Redis-cluster

Dále musí být v clusteru N hlavních uzlů. Každý uzel lze považovat za samostatnou instanci Redis, která ví vše o ostatních uzlech v clusteru. Každý hlavní uzel obsahuje určitý počet slotů. Každý slot patří pouze jednomu hlavnímu uzlu. Všechny sloty musí být rozděleny mezi uzly. Pokud některé sloty nejsou přiděleny, klíče v nich uložené budou nepřístupné. Má smysl provozovat každý hlavní uzel na samostatném logickém nebo fyzickém počítači. Také stojí za to připomenout, že každý uzel běží pouze na jednom jádru, a pokud chcete spouštět více instancí Redis na stejném logickém počítači, ujistěte se, že běží na různých jádrech (toto jsme nezkoušeli, ale teoreticky by to mělo fungovat) . Hlavní uzly v podstatě poskytují pravidelné sharding a více hlavních uzlů umožňuje škálování požadavků na zápis a čtení.

Poté, co jsou všechny klíče rozděleny mezi sloty a sloty jsou rozptýleny mezi hlavní uzly, lze ke každému hlavnímu uzlu přidat libovolný počet podřízených uzlů. V rámci každého takového spojení master-slave bude fungovat normální replikace. Slave jsou potřeba pro škálování požadavků na čtení a pro převzetí služeb při selhání v případě selhání hlavního serveru.
O přesunu z Redis do Redis-cluster

Nyní pojďme mluvit o operacích, které by bylo lepší umět.

K systému budeme přistupovat přes Redis-CLI. Vzhledem k tomu, že Redis nemá jediný vstupní bod, můžete provádět následující operace na kterémkoli z uzlů. U každého bodu zvlášť upozorňuji na možnost provedení operace pod zátěží.

  • První a nejdůležitější věc, kterou potřebujeme, je provoz clusterových uzlů. Vrací stav clusteru, zobrazuje seznam uzlů, jejich role, distribuci slotů atd. Další informace lze získat pomocí informací o clusteru a slotů clusteru.
  • Bylo by hezké mít možnost přidávat a odebírat uzly. Pro tento účel existují operace cluster meet a cluster cancel. Vezměte prosím na vědomí, že zapomenutí klastru musí být aplikováno na KAŽDÝ uzel, jak předlohy, tak repliky. A cluster meet stačí zavolat na jeden uzel. Tento rozdíl může být znepokojující, takže je nejlepší se o něm dozvědět dříve, než se svým clusterem začnete pracovat. Přidání uzlu se v bitvě děje bezpečně a nijak neovlivňuje provoz clusteru (což je logické). Pokud se chystáte odebrat uzel z clusteru, měli byste se ujistit, že na něm nezůstaly žádné sloty (jinak riskujete ztrátu přístupu ke všem klíčům na tomto uzlu). Také nemažte master, který má slave, jinak bude provedeno zbytečné hlasování o nové master. Pokud uzly již nemají sloty, pak je to malý problém, ale proč potřebujeme další možnosti, když můžeme nejprve odstranit podřízené jednotky.
  • Pokud potřebujete násilně prohodit pozice master a slave, udělá to příkaz cluster failover. Když to voláte v bitvě, musíte pochopit, že velitel nebude během operace k dispozici. K přepnutí obvykle dojde za méně než sekundu, ale není atomární. Můžete očekávat, že během této doby některé požadavky na master selžou.
  • Před odebráním uzlu z clusteru by na něm neměly zůstat žádné sloty. Je lepší je znovu distribuovat pomocí příkazu cluster reshard. Sloty budou převedeny z jednoho masteru do druhého. Celá operace může trvat několik minut, záleží na objemu přenášených dat, ale proces přenosu je bezpečný a nijak neovlivňuje chod clusteru. Všechna data tak lze přenášet z jednoho uzlu do druhého přímo pod zatížením a bez obav o jejich dostupnost. Existují však i jemnosti. Za prvé, přenos dat je spojen s určitým zatížením uzlu příjemce a odesílatele. Pokud je uzel příjemce již silně zatížen procesorem, neměli byste jej zatěžovat přijímáním nových dat. Za druhé, jakmile na odesílajícím masteru nezůstane jediný slot, všechny jeho podřízené okamžitě přejdou k masteru, do kterého byly tyto sloty přeneseny. A problém je, že všichni tito otroci budou chtít synchronizovat data najednou. A budete mít štěstí, pokud půjde o částečnou než úplnou synchronizaci. Vezměte to v úvahu a zkombinujte operace přenosu slotů a deaktivace/přenosu podřízených jednotek. Nebo doufejte, že máte dostatečnou rezervu bezpečnosti.
  • Co dělat, když během převodu zjistíte, že jste někde ztratili své sloty? Doufám, že se vás tento problém netýká, ale pokud ano, došlo k opravě clusteru. Přinejmenším rozhází sloty mezi uzly v náhodném pořadí. Doporučuji zkontrolovat jeho fungování tak, že nejprve odeberete uzel s distribuovanými sloty z clusteru. Vzhledem k tomu, že data v nepřidělených slotech jsou již nedostupná, je příliš pozdě obávat se problémů s dostupností těchto slotů. Operace zase neovlivní distribuované sloty.
  • Další užitečnou operací je monitor. Umožňuje vám vidět v reálném čase celý seznam požadavků směřujících do uzlu. Navíc to můžete grepovat a zjistit, zda je tam potřebný provoz.

Za zmínku také stojí master failover procedura. Zkrátka existuje a podle mého názoru funguje skvěle. Nemyslete si však, že pokud odpojíte napájecí kabel na stroji s hlavním uzlem, Redis se okamžitě přepne a klienti si ztráty nevšimnou. V mé praxi dojde k přepnutí během několika sekund. Během této doby budou některá data nedostupná: je zjištěna nedostupnost nadřízeného, ​​uzly hlasují pro nový, podřízené jednotky jsou přepnuty, data jsou synchronizována. Nejlepší způsob, jak se sami přesvědčit, že schéma funguje, je provádět místní cvičení. Zvedněte cluster na svém notebooku, dejte mu minimální zátěž, simulujte pád (například zablokováním portů) a vyhodnoťte rychlost přepínání. Podle mého názoru pouze po jednom nebo dvou dnech hraní tímto způsobem si můžete být jisti fungováním technologie. No, nebo doufat, že software, který používá polovina internetu, pravděpodobně funguje.

Konfigurace

Konfigurace je často první věcí, kterou potřebujete, abyste mohli s nástrojem začít pracovat. A když vše funguje, nechcete se konfigurace ani dotknout. Přinutit se vrátit se k nastavení a pečlivě je projít vyžaduje určité úsilí. V mé paměti jsme měli minimálně dvě vážné poruchy kvůli nepozornosti při konfiguraci. Věnujte zvláštní pozornost následujícím bodům:

  • timeout 0
    Čas, po kterém jsou neaktivní spojení uzavřena (v sekundách). 0 - nezavírat
    Ne každá naše knihovna dokázala správně uzavřít spojení. Vypnutím tohoto nastavení riskujeme, že narazíme na limit počtu klientů. Na druhou stranu, pokud k takovému problému dojde, automatické ukončení ztracených spojení jej zamaskuje a my si toho nemusíme všimnout. Kromě toho byste toto nastavení neměli povolit při používání trvalých připojení.
  • Uložit xy a připojit pouze ano
    Uložení snímku RDB.
    Problémy RDB/AOF podrobně probereme níže.
  • stop-writes-on-bgsave-error ne & slave-serve-stare-data ano
    Pokud je povoleno, pokud se snímek RDB rozbije, hlavní server přestane přijímat požadavky na změnu. Pokud dojde ke ztrátě spojení s masterem, slave může nadále odpovídat na požadavky (ano). Nebo přestane reagovat (ne)
    Nejsme spokojeni se situací, kdy se Redis promění v dýni.
  • repl-ping-slave-period 5
    Po uplynutí této doby se začneme obávat, že se master porouchal a je čas provést proceduru převzetí služeb při selhání.
    Budete muset ručně najít rovnováhu mezi falešnými poplachy a spuštěním převzetí služeb při selhání. V naší praxi je to 5 sekund.
  • repl-backlog-size 1024mb & epl-backlog-ttl 0
    Přesně tolik dat můžeme uložit do vyrovnávací paměti pro neúspěšnou repliku. Pokud dojde vyrovnávací paměť, budete muset provést úplnou synchronizaci.
    Praxe ukazuje, že je lepší nastavit vyšší hodnotu. Existuje mnoho důvodů, proč by replika mohla začít zaostávat. Pokud zaostává, váš pán se s největší pravděpodobností již snaží vyrovnat a plná synchronizace bude poslední kapkou.
  • maximální počet klientů 10000 XNUMX
    Maximální počet jednorázových klientů.
    Podle našich zkušeností je lepší nastavit vyšší hodnotu. Redis zvládá 10k připojení v pohodě. Jen se ujistěte, že je v systému dostatek zásuvek.
  • maxmemory-policy volatile-ttl
    Pravidlo, podle kterého se klíče vymažou při dosažení limitu dostupné paměti.
    Důležité zde není samotné pravidlo, ale pochopení toho, jak se to stane. Redis lze pochválit za schopnost normálně fungovat při dosažení limitu paměti.

Problémy RDB a AOF

Přestože samotný Redis ukládá všechny informace do paměti RAM, existuje také mechanismus pro ukládání dat na disk. Přesněji řečeno, tři mechanismy:

  • RDB-snapshot - kompletní snímek všech dat. Nastavte pomocí konfigurace SAVE XY a zní „Uložte úplný snímek všech dat každých X sekund, pokud se změnilo alespoň Y klíčů“.
  • Append-only file – seznam operací v pořadí, v jakém jsou provedeny. Přidává nové příchozí operace do souboru každých X sekund nebo každých Y operací.
  • RDB a AOF jsou kombinací předchozích dvou.

Všechny metody mají své výhody a nevýhody, nebudu je všechny vypisovat, jen upozorním na body, které podle mého názoru nejsou zřejmé.

Za prvé, uložení snímku RDB vyžaduje volání FORK. Pokud existuje mnoho dat, může to zastavit celý Redis na dobu několika milisekund až sekundy. Systém navíc potřebuje pro takový snímek alokovat paměť, což vede k nutnosti udržovat dvojitou zásobu RAM na logickém stroji: pokud je pro Redis alokováno 8 GB, pak by mělo být na virtuálním stroji k dispozici 16 GB s to.

Za druhé jsou problémy s částečnou synchronizací. V režimu AOF, když je slave znovu připojen, lze místo částečné synchronizace provést úplnou synchronizaci. Proč se to děje, nemohl jsem pochopit. Ale stojí za to si to připomenout.

Už tyto dva body nás nutí zamyslet se nad tím, zda tato data na disku skutečně potřebujeme, když je vše již duplikováno otroky. Data mohou být ztracena pouze v případě, že všechny podřízené jednotky selžou, a to je problém na úrovni „požár v DC“. Kompromisně můžete navrhnout ukládání dat pouze na podřízené jednotky, ale v tomto případě se musíte ujistit, že se tyto podřízené jednotky během obnovy po havárii nikdy nestanou masterem (k tomu je v jejich konfiguraci nastavena priorita podřízených jednotek). Sami se v každém konkrétním případě zamýšlíme nad tím, zda je nutné ukládat data na disk, a odpověď je nejčastěji „ne“.

Závěr

Na závěr doufám, že jsem byl schopen poskytnout obecnou představu o tom, jak redis-cluster funguje pro ty, kteří o něm vůbec neslyšeli, a také jsem upozornil na některé nezřejmé body pro ty, kteří jej používají. na dlouhou dobu.
Děkuji za váš čas a jako vždy vítám komentáře k tématu.

Zdroj: www.habr.com

Přidat komentář