23. Feb 2023
BackendCo je REDIS a jaké je jeho využití v architektuře aplikací
Vystoupil jsem na dvou online akcích: DSC Online Talks on Data a Techband Meetup, kde jsem hovořil o systému REDIS. Těšit se můžete i na druhý díl, kde se dozvíte více o bezpečnosti nebo o tom, jaké je její využití u nás. Záznamy z těchto akcí najdete v článku.
Co je to Redis?
Redis je úložiště datových struktur typu NoSQL, které uchovává data v operační paměti, takže operace nad tímto úložištěm se provádějí nad pamětí RAM, což se vyznačuje vysokou rychlostí.
NoSQL znamená, že se nejedná o relační databázi, data uložená v Redisu nemusí mít předepsanou/předdefinovanou strukturu.
Dále říkáme, že se jedná o tzv. úložiště key-value. To znamená, že data do něj zapisujeme a zároveň k nim přistupujeme prostřednictvím klíče, kterému je přiřazena hodnota. Hodnotou může být libovolná datová struktura s maximální velikostí 512 MB na záznam.
Další důležitou informací o systému REDIS je, že je jednovláknový a dokáže uchovat 2^32 záznamů.
Jaké funkce nám REDIS nabízí?
Nad REDISem lze spustit velké množství funkcí, několik stovek. V mnoha případech se jedná o základní funkci, například pro uložení záznamu PUSH a jeho několika modifikací LPUSH (prepend), RPUSH (append) nad listem atd. Funkce jsou rozděleny do několika kategorií:
Operace nad stringy: GET a SET s různými parametry, INCRBY, DECRBY, GETSET – nastaví novou hodnotu a vrátí původní hodnotu.
Operace nad klíči: DEL – mazání záznamů podle klíče, EXISTS – ověření, zda hledaný klíč existuje, SCAN – cursor-base iterace záznamů, TTL – získání informací o platnosti záznamu a EXPIRE – nastavení platnosti záznamu.
Operace nad listy: LPOP, LPUSH, LTRIM, LRANGE
Operace Geohash – jsou velmi zajímavé, pokud narazíte na komplexnější problém, u kterého budete potřebovat vyřešit vyhledávání pomocí polohy, případně zobrazit velký objem dat na mapě, určitě doporučuju se Geohashi pověnovat. Redis nabízí přímo implementované funkce pro generování geohashe, výpočet vzdáleností atd.
Místo v architektuře aplikací
Tato aplikace se skládá z frontendu, který může být např. v Reactu, Angularu anebo mobilní aplikaci, tedy libovolný konzument API, které je implementované například v Node.js nebo klidně v Javě a databázi SQL. Při provozu očekáváme častá volání enpointu na seznam herních dnů, které vybíráme z databáze a vrátíme klientovi. Při každém volání tedy vstoupíme do databáze, vybereme všechna potřebná data, zformátujeme je a vrátíme. Během hokejového zápasu ale prostřednictvím naší aplikace sleduje zápas několik tisíc lidí, klientská aplikace pravidelně obnovuje data a požadavek na seznam přijde 500× za sekundu. To se začne projevovat na výkonu aplikace, prodlouží se doba, za kterou server požadavek vyřídí, a v nejhorším případě se služba stane nedostupnou, začne timeoutovat. Jak nám může v tomto případě pomoct Redis? Jedním z nejčastějších využití Redisu je ukládání do cache. Na serveru vedle aplikačního backendu a aplikace (případně na samostatném serveru, což je vhodnější) spustíme server Redis.
Aplikaci následně upravíme tak, aby se po příchodu požadavku na seznam nejprve podívala do Redisu, zda se tam tento seznam nenachází. Pokud ano, vrátíme ho jako odpověď na request. Pokud ne, vybereme data z databáze, zformátujeme je do tvaru požadovaného v odpovědi, uložíme je do Redisu a vrátíme odpověď klientské aplikaci.
U ukládaného záznamu v Redisu je důležité nastavit platnost, např. na 5 sekund. Co jsme tímto úsilím získali? Pokud nám za sekundu chodí v průměru 500 požadavků na podrobnosti daného zápasu, do databáze vstoupíme pouze 12× za minutu namísto 30×. Zbývající požadavky budou vyřizovány z cacheovaného záznamu v Redisu, kdy načítání z Redisu je výrazně levnější a rychlejší operace než přístup k záznamům na disku.
Online záznam z DSC:
Kdy je vhodné ho použít?
Teď jsme si popsali jeden z možných případů použití Redisu jako cache, dalšími velmi užitečnými způsoby, jak nám Redis může pomoct, jsou:
Queue
S frontami jste se už určitě setkali nebo se u většiny projektů setkáte. Využití mohou najít nejen při řízení zpracování dat. A právě tady nám Redis může usnadnit práci. Redis má přímo implementované funkce PUSH a POP a jejich různé modifikace, včetně velmi užitečných funkcí blokování fronty při přístupu většího počtu klientů.
Leaderboards
Tabulka s výsledky. Tento případ se může zdát velmi specifický, ale Redis se skutečně často využívá pro účely uchovávání žebříčku, ať už soutěžících, nebo jiného setu záznamů, které je třeba uspořádat podle počtu bodů a pracovat s nimi. Redis obsahuje sadu funkcí pro práci s žebříčky, např.
ZADD – uložení skóre soutěžícího spolu s možností pomocí parametru určit, zda se má stávající záznam upgradnout, nebo ignorovat, a to i v závislosti na výši skóre
ZREVRANGE – vytažení žebříčku v rozsahu definovaném indexy
ZRANK – vrací skóre soutěžícího
Tyto funkce jsme využili i u nás v projektu Fantasy Liga, kde se k uchovávání a práci s žebříčkem soutěžících využívá kromě cache i Redis.
Counting
Počítání všeho, co vás napadne. Redis je velmi užitečný pro shromažďování statistik a obsahuje i sadu funkcí Inkrement/Dekrement, které se často používají i u relačních databází.
Kdy není vhodné používat Redis nebo co je třeba vzít v úvahu, když se rozhodnete Redis ve svém projektu použít.
Asynchronní zápis na disk
Redis je ve svém výchozím nastavení pouze in-memory úložiště. Perzistence dat na disku je možná, ale je třeba tuto funkci zapnout. Je ale třeba vzít v úvahu, že i po zapnutí perzistence je zápis na disk asynchronní, takže v případě výpadku serveru můžeme přijít o data, která na disk nebyla zapsána.
Všechna data jsou v paměti RAM
Pokud chcete používat Redis jako primární úložiště dat, je potřeba zvážit očekávaný objem dat. Skutečnost, že všechna data jsou uložena v RAM, je obrovskou výhodou z hlediska rychlosti operací IO, ale z hlediska požadované kapacity a aktuálních cen například za VM v cloudu je třeba mít se na pozoru.
Výpadky (selhání) serveru
Služba je dostupná, ale při výpadku serveru je nedostupná. Stejný problém se může vyskytnout i u jiných databází nebo non-HA systémů, takže se nejedná o specifický nedostatek v případě Redisu. Spíš jsem chtěl poukázat na to, že v případě Redisu je tento problém částečně řešitelný prostřednictvím Redis Clusteru, kde může jiný funkční node zastoupit spadlý node, ale clusteru se bude věnovat samostatná část.
Design aplikace
Jelikož je práce s Redisem v mnoha ohledech specifická, je důležité mít už při designování (nemyslím tím design UX/UI) aplikace na paměti jeho funkce a vlastnosti, pokud se má používat jako primary store. Například u databází SQL je často snazší nahradit databázový systém jiným příbuzným systémem.
Jakých chyb je dobré se vyvarovat při používání Redisu?
Za jeden z největších problémů bych určitě označil nedostatečné zabezpečení, nepoužívání hesla pro přístup a otevření Redisu světu. O bezpečnosti si povíme víc v samostatné části, ale chtěl jsem ji zmínit i tady, protože je velmi důležitá.
Příkaz KEYS
Ve většině případů se v tutoriálech příkaz KEYS ukazuje jako první. Příkaz KEYS je ale synchronní příkaz a v závislosti na počtu záznamů může na dlouhou dobu přetížit server, protože během provádění tohoto příkazu nemůže obsluhovat jiné požadavky. Většinou se ale používá jen na debugging během vývoje.
Číslované databáze (SELECT)
V Redisu můžete pracovat nad vícero databázemi a přepínat mezi nimi, ale tyto databáze nejsou navrženy příliš šťastně. Nejsou od sebe dostatečně izolované. Pokud byste nad jednou databází spustili příkaz KEYS a ta by obsahovala příliš mnoho záznamů, odstavili byste tím všechny databáze. Zátěž na jednu instanci je tedy sdílená. Sami autoři Redisu to označili za jednu z největších chyb v designu Redisu.
Nový connection pro každý request
Správně by se mělo udržovat otevřené připojení a mělo by se využívat pro víc příkazů, namísto abyste pro každý příkaz otevírali a zavírali nové připojení. Zejména v PHP býval (údajně) kdysi problém držet si jedno otevřené připojení.
Problém Hot Key
Pokud máme v Redis Clusteru jeden klíč, ke kterému přistupujeme velmi často, přistupujeme v podstatě velmi často k jednomu nodu, jelikož daný záznam se nachází na jednom nodu. Tento problém je třeba řešit už v návrhu aplikace, aby se této situaci předešlo.
Online záznam z Techband Meetupu:
Nenechte si ujít novinky z našeho světa a přihlaste se k odběru newsletteru!