
Redis report
Redis je open source, in-memory, key-value databáze. Redis je velmi zajímavá a unikátní databáze, která preferuje rychlost, dostupnost, toleranci a horizontální škálovatelnost na úkor persistence. Hlavní případ užití Redis databáze není dlouhodobé a spolehlivé uchovávání dat, nýbrž operace jako caching nebo message broking.
Úvod
Není databáze jako databáze. Na jedné straně existují SQL databáze s dekádami pokroků v oblasti informační teorie a vývoje. Tyto databáze nabízí obrovské množství nástrojů a možností, jak strukturovat data, uchovávat data a jak složitě nad daty vyhledávat. Na druhé straně je Redis. Key-value databáze, jejíž základní princip lze pochopit během jedné minuty, a která se ani jako persistentní databáze neužívá. I přes to lze nalézt databázi Redis v překvapivě mnoha komerčních projektech1.
Redis je databáze, která se nepoužívá tak standartně, jak mohou někteří programátoři předpokládat. Její vlastnosti, jako například fakt, že je to pouze in-memory databáze, ji dělají perfektním nástrojem pro řešení problémů s cachování nebo message brokingem1.
Redis je díky svým unikátním užitím perfektním příklad, jak flexibilní i multifunkční dokážou databáze být.
Základní vlastnosti Redis
Redis je open source, in-memory, key-value databáze. Princip Redis databáze je tedy ukládání dat na základě jejich klíče. Celá Redis databáze funguje v operační paměti zařízení s možností různých módů persistentních snapchotů2.
Redis z pohledu CAP teorému nabízí consistency a partition tolerance na úkor availability – nicméně zde není CAP kategorizace úplně přesná. Redis má vlastnosti BASE – Basically Available, Soft State, Eventual Consistency.
Díky tomu, že Redis operuje pouze s operační pamětí, jsou základní operace nad daty pomocí jejich klíče velmi rychlé – dokonce asymptoticky konstantní. Operační paměť je bohužel dražší zdroj, nežli objemnější persistentní paměti. Redis naštěstí nabízí bohaté horizontální škálování v podobě replikace, shardingu a clusterování. Redis zároveň nabízí mechanismy jako časem limitovaná životnost dat nebo Least Recently Used (LRU) evikce se zadaným paměťovým limitem34.
Vlastnosti této databáze jí dělají perfektním řešením pro cache nebo message broking. Elementární příkazy pro obsluhu Redis databáze pomocí CLI (nebo obdobně pomocí API) jsou:
SET key value
GET key
EXISTS key
Ostatní příkazy jsou pouze obdoby výše uvedených s prefixy podle datových typů, vyjma obecných příkazů jako získání všech klíčů (KEYS
), vymazání všech klíčů (FLUSHALL
) apod4.
Datové typy a příkazy
Redis v oblasti datových typů poskytuje širokou škálu možností. Nejjednodušší a nejpoužívanějším datovým typem je bezkonkurenčně String. Vzhledem k populárnímu užití ve webových technologiích to může být předvídatelné, zvláště proto, že masivně používané formáty a protokoly jako JSON, XML nebo HTML, jsou právě textové4.
Klíče v Redis databázi mohou být jakákoliv binární sekvence, například text. Maximální délka klíče je 512 MB, nicméně tak dlouhé klíče nejsou doporučovány4.
String je nejjednodušší datový typ v databázi Redis. Díky masivnímu použití textových protokolů, textových formátů a snadnému lidskému porozumění se jedná o nejpoužívanější datový formát. String je ovládán elementárními příkazy popsané v předchozí kapitole. V případě některých příkazů, například pro číselné operace typu atomický inkrement, Redis interně reprezentuje String jako číslo a matematické operace provede korektně. String tedy zastává i čísla, booleanovské hodnoty, binární hodnoty apod.4.
List je kolekce Stringů. Je možné vkládat nové položky na začátek listu nebo na konec listu. Je možné také z těchto konců odebírat. Z listu lze rychle vrátit koncové hodnoty nebo vrátit celý list v lineárním asymptotickém čase4.
Set je množina unikátních Stringů. Je možné do množiny přidávat, odebírat nebo testovat existenci v konstantním asymptotickém čase4.
Hash je key-value kolekce poskytující hodnoty pro klíče4.
Sorted set je stejný datový typ jako Set, akorát s tím rozdílem, že hodnoty v Sorted setu jsou zarovnány dle uživatelem definovaných hodnot (=score). Nevýhodou je nutná definice score, výhodou jsou velmi rychlé operace pracující s tímto score, například výběr hodnot se score v daném intervalu4.
Bitmapy nejsou datový formát jako takový, nýbrž sada metod nad typem String, specializující se na práci s bity. Pokud je tedy potřeba uložit binární hodnotu, ukládá se pomocí nějaké bitmapové metody jako String4.
HyperLogLog je datová probabilistická struktura specializovaná pro počítání unikátních hodnot (kardinalita setu). Normálně by bylo potřeba lineárně paměti vzhledem k počtu hodnot, nicméně HyperLogLog funguje na systému pravděpodobností a paměť potřebuje asymptoticky konstantní. Standartní error tohoto datového typu je však 1 %4.
Každý výše uvedený datový typ disponuje vlastní unikátní sadou metod. Například, datový typ string má následující základní příkazy pro manipulaci:
> SET key value
OK
> GET key
"value"
A datový typ Set poskytuje následující základní příkazy, z nichž všechny mají prefix "S":
> SADD setKey 1 2 3
(integer) 3
> SMEMBERS setKey
1. 3
2. 1
3. 2
Obdobně to platí pro všechny datové typy. Jejich příkazy jsou unikátní a většinou mají i unikátní prefix pro snadnou viditelnost, se kterým datovým typem se nyní pracuje4.
Persistence
Databáze Redis pracuje pouze na operační paměti počítače. Díky tomu je Redis tak rychlý. Redis však umí jednorázově či pravidelně ukládat svůj stav na disk – záleží na tom, v jakém módu je Redis databáze nastavena5.
RDN (Redis Database) je mód, ve kterém se v definovaném časovém intervalu pořídí aktuální stav (snapshot) databáze a uloží se na disk. Stav v podobě souboru je velice kompaktní a ideální pro občasné zálohy databáze a rychlé restarty, nicméně v případě výpadku databáze jsou ztracena všechna data od poslední zálohy5.
AOF (Append Only File) je mód, ve kterém databáze každou operaci uloží do logů. Při příštím startu databáze se rekonstruuje aktuální stav podle logů. AOF mód sice zálohuje kompletně všechna data v případku výpadu, nicméně kvůli nutnosti forku databáze je pomalejší a častý zápis do logů znamená potencionálně větší šanci na korupci dat v případě náhlého výpadku5.
No persistence je mód, ve kterém databáze Redis kompletně ignoruje persistence/stav z předchozích běhů5.
RDB + AOF je mód kombinující přístup RDB i AOF. V případě nové instance Redis je preferována rekonstrukce pomocí AOF, jelikož je kompletnější5.
V případě, že je pro uživatele Redisu důležitá bezpečnost dat, jako například u konvenčních SQL databází, je doporučeno použít kombinaci RDB a AOF. V opačném případě je doporučeno použít pouze RDN nebo žádný persistentní mechanismus5.
Škálování
Horizontální škálování je pro Redis důležité, už jenom proto, že operační paměti jsou o dost dražší, než paměti persistentní, zvláště při velkých kapacitách.
Redis nabízí bohatou škálu možností, jak databázi škálovat a poskytnout větší dostupnost na úkor konzistence. Základní jednotka Redis škálování je Redis Cluster, v němž lze provádět operace jako sharding nebo replikace jednotlivých uzlů. Uzly uprostřed Redis Clusteru jsou propojeny úplnou topologií pro minimální nutnost směřování. Redis Clustery lze i dále škálovat podle geo lokace apod. Možností škálování je v Redis ekosystému bohatě 67.
Redis zároveň i poskytuje službu Redis Enterprise, což je cloudová služba, kde lze zakoupit a nastavit Redis Clustery přes jednoduché UI s možností hostování clusterů v různých zemích8.
Partitioning (sharding)
Rozdělení jedné Redis databáze na dvě (a více) je v případě key-value databáze jednoduché. Vzhledem k tomu, že k jakémukoliv přístupu poskytujeme klíč, stačí klíč směřovat na odpovídající instanci databáze obsahující správnou hodnotu, a to za použití nějakého pravidla:
Range partitioning je seznam manuálně nastavených pravidel, podle kterých směřujeme dotazy s konkrétním patternem klíče. Pokud je například potřeba držet všechna data o uživatelích v jedné instanci, napíšeme pravidlo, že všechny klíče splňující pattern /user:ID/
, kde ID je v rozmezí 1 až 10000, budou směřována na instanci #1. To má však své nevýhody toho, že musíme manuálně definovat pravidla pro klíče9.
Hash partitioning přijme klíč, aplikuje na něj hash funkci transformující klíč na číslo (například crc32), které se zmodulí počtem instancí a výsledné číslo je číslo cílové instance. Tento přístup nevyžaduje žádný dozor od programátora, nicméně zamezuje nám aktivně držet související data v jedné instanci9.
instanceID = crc32(key) mod instanceCount
Některé Redis operace vyžadují, aby byla data v jedné instanci, nebo je efektivnější je držet v jedné instanci, proto se v některých situacích vyplatí využít Range partitioning8. V jiných situacích zase může být praktičtější Hash partitioning, jelikož docílíme rovnoměrného pokrytí bez jakékoliv námahy.
Správné směřování dotazu dle stanovených pravidel na správnou instanci může být zřízeno buď:
- Klientem, který dotaz odesílá
- Proxy službou, která obstarává směřování
- Jakoukoliv Redis instancí, která dotaz vyřídí nebo přepošle na správnou instanci 9
Replikace
Každý uzel uprostřed Redis Clusteru lze replikovat. V takovém případě jsou všechny uzly slaves, mimo jednoho, který je master. Master uzel obstarává všechny operace. Operace, které mohou být delegovány na slaves, jsou akorát operace na čtení. Master své slaves postupně aktualizuje6.
Není garantováno, že se všechny zprávy do slaves propíšou správným způsobem. Například, pokud master obdrží a provede aktualizace, spadne dříve, než zašle aktualizace otrokům a je zvolen nový master, změna se do otroků nikdy nepropíše, i když originální master (nyní již slave) opět naběhne. Podobných situací je celá řada6.
Replikace je ideální v případě operací intenzivních na čtení6.
Pro maximální účinnost je vhodné aktivovat Multi AZ mód, který se ujistí, že otroci se nenachází na stejných fyzických uzlech pro maximální dostupnost8.
Geodistribuce
Je možné vytvořit více Redis Clusterů, běžících v různých fyzických datacentrech. V takovém případě musí mít každý cluster jeden master shard pro každý shard – tedy pro jeden shard vznikne globálně více masterů8.
Lokální uživatelé pracují s lokálním datovým centrem a lokálním masterem. Clustery společně však globálně komunikují a v případě kolize hodnot mezi masters aplikují pravidlo Last Write Wins, tedy nejnovější hodnota má přednost. Redis tento přístup nazývá Geo-Distributed Active-Active Redis10.
Příkladový diagram Geo-Distributed Active-Active databáze s replikací, shardingem a Multi AZ je možné shlédnout na obrázku č. 1.
Instalace a využití
Redis CLI a lokální instance
Redis je možné snadno nainstalovat pomocí preferovaného správce balíčků, například na Linux systémech příkazem sudo apt-get install redis
.
Redis server lze lokálně spustit pomocí příkazu redis-server
.
Pro snadné ovládání Redis serveru lze použít Redis CLI (Command Line Interface). Příkazem redis-cli
lze přistoupit k lokálnímu Redis serveru.
Ve spuštěném interaktivním CLI je možné zadávat příkazy, například:
> SET myName Tonda
OK
> GET myName
"Tonda"
> DEL myName
(integer) 1
> GET myName
(nil)
Redis jako cache v node.js aplikaci
U node.js je možné Redis API nainstalovat jako balíček s názvem "redis". V aplikaci stačí pro spojení s lokálním klientem využít tovární metodu:
const Redis = require("redis")
const redisClient = Redis.createClient()
Představme si, že máme webovou aplikaci. Tato webová aplikace poskytuje e-shop pro vozidla. Vozidla jsou však většinou neměnná, a tak není třeba při každém požadavku stavět celou HTML stránku, jelikož to vyžaduje například komunikaci s databází, s jinými servery, s file systémem apod. Na server tedy můžeme aplikovat Redis cache a postavené HTML uložit alespoň na minutu a ušetřit si tak časté a složité stavění výsledného HTML. Redis sám umí po předem daném čase své klíče invalidovat pomocí zadaného TTL (Time-To-Live).
Následující pseudo-js-kód ukázka demonstruje využití Redis jako cache přímo pomocí programátorského API:
// Tvoří HTML pro vozidla
function CreateCarHTML(id) { ... }
// Endpoint pro vozidla
app.get("/car/:id", async (req, res) => {
const carId = req.params.id
// Zeptáme se Redis, zda již nemáme potřebné HTML
redisClient.get("car:" + carId, async (error, carHTML){
// Redis odpověděl, že máme error
if (error)
console.error(error)
// Redis odpověděl, že tento klíč nemá
else if (carHTML == null){
const newCarHTML = CreateCarHTML(carId)
// Ulož newCarHTML do Redis s Time-To-Live na 60 sec
redisClient.setex("car:" + carId, 60, newCarHTML)
// Vrať HTML
return res.send(newCarHTML)
}
// Redis našel existující HTML
else {
// Vrať HTML
return res.send(carHTML)
}
})
})
Redis jako cache middleware nebo message broker
Redis lze použít přímo z aplikačního API, nicméně lze jej aplikovat i jako middleware v architektonickém návrhu aplikace.
Mezi ideální middleware služby, jež může Redis podporovat, patří cache nebo messsage broker.
Je možné si například na webu Enterprise Redis koupit Redis jako cache službu a propojit s AWS, Azure nebo Google Cloud.
Závěr
Redis je velmi zajímavá a unikátní databáze, která preferuje rychlost, dostupnost, toleranci a horizontální škálovatelnost na úkor konzistence a persistence.
Hlavní případ užití Redis databáze není dlouhodobé a spolehlivé uchovávání dat, nýbrž operace jako caching nebo message broking.
Redis definitivně patří mezi unikáty, a to v dobrém slova smyslu. V praxi na něj lze narazit poměrně často. Není se čemu divit, používat Redis je velmi jednoduché, efektivní a možné jej škálovat do velkých výšin.
Redis [online] [visited on 2021-11-18]. Available from: https://redis.io/↩↩
WEB DEV SIMPLIFIED. Redis Crash Course [online]. 2021 [visited on 2021-11-19]. Available from: https://www.youtube.com/watch?v=jgpVdJB2sKQ.↩
Introduction to Redis – Redis [online] [visited on 2021-11-18]. Available from: https://redis.io/topics/introduction.↩
Data types – Redis [online] [visited on 2021-11-19]. Available from: https://redis.io/topics/data-types.↩↩↩↩↩↩↩↩↩↩↩↩
Redis Persistence – Redis [online] [visited on 2021-11-19]. Available from: https://redis.io/topics/persistence.↩↩↩↩↩↩
Redis Cluster Specification – Redis [online] [visited on 2021-11-18]. Available from: https://redis.io/topics/cluster-spec.↩↩↩↩
Redis cluster tutorial – Redis [online] [visited on 2021-11-18]. Available from: https://redis.io/topics/cluster-tutorial.↩
AUSTRALIA, OCTO Technology. High Availability and Scalability with Redis Enterprise [Medium] [online]. 2019-04-09 [visited on 2021-11-18]. Available from: https://medium.com/@octoz/high-availability-and-scalability-with-redis-enterprise-54a48edcce17.↩↩↩↩
Partitioning: how to split data among multiple Redis instances – Redis [online] [visited on 2021-11-19]. Available from: https://redis.io/topics/partitioning.↩↩↩
Geo-Distributed Active-Active Redis Applications | Redis Documentation Center [online] [visited on 2021-11-19]. Available from: https://docs.redis.com/latest/rs/concepts/intercluster-replication/.↩