28. Jun 2021Backend & DevOps

Čo je REDIS a aké ma využitie v architektúre aplikácií

Tohtoročný jún sa v mojom prípade niesol v znamení zaujímavých eventov. Vystúpil som na dvoch online eventoch: DSC Online talkov na tému dáta a Techband Meetupu, kde som rozprával na tému REDIS. Tešiť sa môžeš aj na druhý diel kde sa dozvieš viac o bezpečnosti či aké ma využitie u nás. Záznamy eventov nájdeš v článku.

Dušan DragulaHead of DevOps

Čo je to Redis?

Redis je úložisko dátových štruktúr typu NoSQL, ktoré uchováva údaje v operačnej pamäti, teda operácie nad týmto úložiskom sú vykonávané nad pamäťou RAM, čo sa vyznačuje vysokou rýchlosťou.
 

NoSQL znamená, že nejde o relačnú databázu, údaje uchovávané v Redise nemusia mať predpísanú / preddefinovanú štruktúru.

Ďalej hovoríme, že ide o tzv. key-value úložisko. To znamená, že údaje do neho zapisujeme a tiež k údajom pristupujeme prostredníctvom kľúča, ku ktorému je priradená hodnota. Hodnotou môže byť ľubovoľná dátová štruktúra s maximálnou veľkosťou 512 MB na každý záznam.

Ďalšími dôležitými informáciami o REDISe sú, že je single-thread a dokáže uchovať 2^32 záznamov.
 

Aké funkcie nám REDIS ponúka?

Najvyužívanejšie funkcie REDIS

 

Funkcií, ktoré je možné nad REDISom spúšťať je veľké množstvo, niekoľko stoviek. Vo veľa prípadoch ide o základnú funkciu, napr. pre uloženie záznamu PUSH a viacero jej modifikácií LPUSH (prepend), RPUSH (append) nad listom a pod. Funkcie sa delia do viacerých kategórií:
 

Operácie nad stringami: GET a SET s rôznymi parametrami, INCRBY, DECRBY, GETSET - nastaví novú hodnotu a vráti pôvodnú hodnotu.
 

Operácie nad kľúčmi: DEL - mazanie záznamu podľa kľúča, EXISTS - overenie či hľadaný kľúč existuje, SCAN - cursor- base iterácia záznamov, TTL - získanie informácie o platnosti záznamu a EXPIRE - nastavenie platnosti záznamu.
 

Operácie nad listami: LPOP, LPUSH, LTRIM, LRANGE
 

Geohash operácie - sú veľmi zaujímavé, pokiaľ sa stretnete s komplexnejším problémom, pri ktorom budete potrebovať riešiť vyhľadávanie pomocou polohy, prípadne zobrazovanie veľkého objemu údajov na mape, určite odporúčam pozrieť sa na Geohash. Redis ponúka funkcie priamo implementované na generovanie geohashu, výpočet vzdialeností a pod. 
 

Miesto v architektúre aplikácii

 

Grafické znázornenie využitia REDIS v architektúre aplikácie

 

Táto aplikácia pozostáva z Frontendu, ktorý môže byť napr. v Reacte, Angulari alebo mobilná aplikácia, teda ľubovoľný konzument API, ktoré je implementované napr. v Node.js alebo kľudne v Java a SQL databázy. Pri prevádzke očakávame časté volanie endpointu na zoznam hracích dní, ktoré vyberáme z databázy a vrátime klientovi. Každým volaním teda vojdeme do databázy, vyberieme všetky potrebné údaje, naformátujeme ich a vrátime. Počas hokejového zápasu však prostredníctvom našej aplikácie sleduje zápas niekoľko tisíc ľudí, klientská aplikácia údaje pravidelne obnovuje a za jednu sekundu príde požiadavka na zoznam 500x. To sa začne prejavovať na výkone aplikácie, zvýši sa čas, za aký dokáže server vybaviť požiadavku až v najhoršom prípade sa stane služba nedostupná, začne timeout-ovať. Ako nám vie v takomto prípade pomôcť Redis? Jedno z najčastejších využití Redisu je cacheovanie. Na serveri, vedľa aplikačného backendu a aplikácie (prípadne na samostatnom serveri, čo je vhodnejšie), spustíme Redis server.

Aplikáciu následne upravíme tak, aby sa po príchode požiadavky na zoznam najskôr pozrela do Redisu, či sa tam tento zoznam nenachádza. Ak áno, vrátime ho v odpovedi na request. Ak nie, vyberieme údaje z databázy, naformátujeme ich na tvar vyžadovaný v odpovedi, uložíme ho do Redisu a vrátime odpoveď klientskej aplikácii.
 

Dôležité je nastaviť platnosť ukladaného záznamu v Redise, napr. na 5 sekúnd. Čo sme týmto snažením získali? Ak nám chodí v priemere 500 požiadaviek na detail daného zápasu za sekundu, do databázy vstúpime behom jednej minúty namiesto 30k krát iba 12 krát. Zvyšné požiadavky budú vybavené z cacheovaného záznamu v Redise, kde načítanie z Redisu je výrazne lacnejšia a rýchlejšia operácia ako prístup k záznamom na disku.

Online záznam z DSC:

Kedy je vhodné ho použiť?
 

Teraz sme si popísali jeden z možných prípadov využitia Redisu ako cache, ďalšími veľmi užitočnými spôsobmi, ako nám vie Redis pomôcť sú:
 

Queue
 

S frontami ste sa už určite stretli alebo sa stretnete pri väčšine projektov. Využitie môžu nájsť nielen pri riadení spracovania údajov a práve tu nám vie Redis uľahčiť prácu. Redis má priamo implementované funkcie PUSH a POP a ich rôzne modifikácie, vrátane veľmi užitočných funkcií blokovania fronty pri prístupe viacerých klientov.
 

Leaderboards
 

Tabuľka s výsledkami. Tento prípad sa môže zdať veľmi špecifický, ale naozaj je Redis využívaný často na účely uchovávania rebríčka či už súťažiacich alebo iného setu záznamov, ktoré je potrebné usporadúvať podľa skóre a pracovať s ním. Redis obsahuje set funkcií na prácu s rebríčkami, napr.

ZADD - uložiť skóre súťažiaceho spolu s možnosťou pomocou parametra určiť, či existujúci záznam má byť upgradenutý alebo ignorovaný a to aj v závislosti od výšky skóre, 

ZREVRANGE - vytiahnuť rebríček v rozsahu definovanom indexami

ZRANK - vráti skóre súťažiaceho

Tieto funkcie sme využili aj u nás pri projekte Fantasy liga, kde je Redis okrem Cache využitý aj na uchovávanie a prácu s rebríčkom súťažiacich.

Counting
 

Počítanie čohokoľvek, čo vás napadne. Redis je veľmi užitočný na zbieranie štatistík, a obsahuje aj set funkcií typu Inkrement / Dekrement, ktoré sú využívané často aj pri relačných databázach.

Kedy nie je vhodné použiť Redis alebo čo treba zvážiť predtým, ako sa rozhodnete Redis na svojom projekte použiť.
 

Asynchrónny zápis na disk
 

Redis je vo svojej defaultnej konfigurácii iba in-memory úložisko. Perzistencia údajov na disku je možná, no je potrebné túto funkciu zapnúť. Treba však brať do úvahy to, že aj po zapnutí perzistencie prebieha zápis na disk asynchrónne, teda v prípade zlyhania servera môžeme stratiť údaje, ktoré neboli zapísané na disku.
 

Všetky údaje sú v RAM
 

V prípade, že by ste chceli použiť Redis ako primárne úložisko údajov, je potrebné zvážiť očakávaný objem údajov. To, že sú všetky údaje uložené v RAM je obrovská výhodu z pohľadu rýchlosti IO operácií, avšak z pohľadu potrebnej kapacity a aktuálnych cien napr. za VM v cloude treba byť opatrný.
 

Výpadky (zlyhania) servera
 

Služba je dostupná, avšak pri zlyhaní servera je nedostupná. Rovnaký problém môže nastať aj pri iných databázach alebo non-HA systémoch, teda nejde o špecifický nedostatok v prípade Redisu, chcel som tu skôr poukázať na to, že v prípade Redisu je tento problém čiastočne riešiteľný prostredníctvom Redis Clustera, kedy dokáže iný funkčný node zastúpiť spadnutý node, ale o Clusteri bude samostatná časť.
 

Dizajn aplikácie
 

Nakoľko je práca s Redisom v mnohých aspektoch špecifická, je potrebné už pri dizajnovaní (nemyslím UX / UI dizajn) aplikácie myslieť na jeho funkcie a vlastnosti ak má byť použiteľný ako primary store. Napr. pri SQL databázach je častokrát databázový systém jednoduchšie vymeniteľný za iný príbuzný.
 

Akým chybám je dobré sa vyhnúť pri použití REDISu?
 

Určite za jeden za najväčších problémov by som označil nedostatočné zabezpečenie, nepoužívanie hesla pre prístup a otvorenie Redisu do sveta. Viac o bezpečnosti si povieme v samostatnej časti, avšak chcel som to spomenúť aj tu, nakoľko je to veľmi dôležité.
 

Príkaz KEYS
 

Vo väčšine prípadov je príkaz KEYS ukazovaný ako prvý v tutorialoch. KEYS je však synchrónny prikaz a v závislosti od počtu záznamov môže na dlhu dobu zaťažiť server, nakoľko počas vykonávania tohto príkazu nedokáže obsluhovať ďalšie požiadavky. Väčšinou sa však používa len na debug účely pri vývoji.
 

Číslované databázy (SELECT)
 

V Redise môžete pracovať nad viacerými databázami a prepínať sa medzi nimi, avšak tieto databázy nie sú veľmi šťastne navrhnuté. Sú od seba nedostatočne odizolované. Ak by ste nad jednou databázou spustili príkaz KEYS a obsahuje priveľa záznamov, tak odstavíte všetky databázy. Zaťaženie na jednu inštanciu je teda zdieľané. Samotní autori REDISu ich označili za jednu z najväčších chýb v dizajne REDISU.
 

Nový connection pre každý request
 

Správne by sa mal udržiavať otvorený connection a využívať ho pre viacero príkazov, namiesto otvárania a zatvárania nového connectionu pre každý príkaz. Predovšetkým pri PHP s tým (vraj) kedysi problém držať si jeden otvorený connection.
 

Hot Key problém
 

V Redis clustri, pokiaľ máme jeden kľúč, ku ktorému pristupujeme veľmi často, tak v podstate pristupujeme veľmi často k jednému node-u, nakoľko daný záznam sa nachádza na jednom node. Tento problém je potrebné riešiť už v aplikačnom návrhu, aby k takejto situácii nedošlo

Online záznam z Techband Meetup:

Nezmeškaj novinky z nášho sveta a prihlás sa na newsletter!

Dušan DragulaHead of DevOps