Redis

V Techband je naším cieľom tvoriť IT základňu hviezdnych developerov a mimo iného podporovať ich a aj širšiu verejnosť, v osobnostnom a profesionálnom rozvoji v oblasti IT a technológií. Práve preto sme sa koncom roka 2020 rozhodli spustiť sériu Techband meetup-ov zameraných na rozvoj hard-skills, konkrétne na jednu z najpopulárnejších technológii – JavaScript.

V tomto článku vám prinášame bližšie predstavenie témy “Node.js – Redis”, o ktorej na jednom z našich JavaScript meetup-ov rozprával speaker Dušan Dragula – my sme ju následne spracovali do písomnej formy na náš blog.

 

Čo je to Redis?

Redis je v zásade úložiskom dátových štruktúr typu NoSQL, ktoré uchováva údaje v operačnej pamäti. Znamená to, že operácie nad týmto úložiskom sú vykonávané nad pamäťou RAM, čo sa vyznačuje vysokou rýchlosťou. Čo sa týka NoSQL, tak tu sa nejedná o relačnú databázu a vďaka tomu nemusia mať údaje uchovávané v Redis-e predpisanú štruktúru. Ide tam o takzvané kyber úložisko, do ktorého zapisujeme údaje a následne k ním tiež pristupujeme prostredníctvom nejakého kľúča s priradenou hodnotou. Ďalšou základnou informáciou o Redis-e je fakt, že je single-threaded a že dokáže uchovať 2^32 záznamov. Maximálna veľkosť jedného záznamu, ktorý môže byť uchovaný v Redis-e, je 512 MB.

 

Aké funkcie nám Redis ponúka?

Funkcií, ktoré je možné nad Redis-om spúšťať, je naozaj obrovské množstvo – počítajú sa v stovkách. Vo veľa prípadoch však ide o jednu základnú funkciu, napríklad pre uloženie záznamu existuje funkcia push, a následne viacero jej modifikácií, ako je napríklad l-push, r-push alebo tiež operácie nad list-om, ktoré na jeho začiatok alebo koniec vedia bez akéhokoľvek operačného zásahu uložiť záznam.

Celkovo sa funkcie delia do viacerých kategórií. Najpoužívanejšími sú práve funkcie nad string-ami, kde medzi základné patria funkcie get a set, ďalej obsahujú tiež funkcie inkrementácie a dekrementácie hodnôt. Zaujímavá je aj funkcia getset, ktorá nám umožňuje jedným krokom pristúpiť k pôvodnej hodnote, ale zároveň aj nastaviť novú. Mimo toho existujú napríklad aj operácie nad kľúčami, kde je napríklad možné vymazať záznam podľa kľúča alebo kontrolovať, či existuje. Často používaná je tiež funkcia scan založená na rekurzore, ktorou dokážeme iterovať záznamy. Za dôležitú sa považuje aj funkcia ttl, pomocou ktorej dokážeme zistiť informáciu o platnosti záznamu v Redis-e, a v nadväznosti na to funkcia expar, ktorá zase dokáže nastaviť časovú platnosť záznamu. To má veľký význam hlavne pri využívaní Redis-u ako cache.

Okrem toho sú veľmi zaujímavou skupinou operácií sú aj geo-hash operácie. Tie nám slúžia najmä vtedy, keď sa stretneme s komplexnejším problémom, kde potrebujeme riešiť vyhľadávanie pomocou polohy alebo GPS súradníc, prípadne keď potrebujeme zobrazovať veľké množstvo údajov na mape. Téma geo-hash operácií je veľmi rozsiahla a netýka sa iba Redis-u, avšak Redis samotný ponúka veľké množstvo funkcií, ktoré sa v rámci geo-hashovania dajú implementovať.

 

Aké má Redis miesto v architektúre aplikácií?

Predstavme si príklad vývoja webovej aplikácie, prípadne API pre mobilnú aplikáciu, na zobrazenie zoznamu dní, kedy sa hrajú hokejové zápasy (toto je zároveň reálna situácia vývoja aplikácie pre Tipos Extraligu). Táto aplikácia môže pozostávať z front-endu postavenom napríklad na React-e alebo Angular-i (v princípe však na ľubovoľnom konzumente API, ktoré máme vystavené backend-om). API môže byť implementované v ľubovoľnom jazyku, v našom prípade to bude Node.js, v rámci neho konkrétne framework Total.js. Aplikácia ďalej pozostáva z SQL alebo NoSQL databázy – v našom prípade projektu Tipos Extraliga bola na schéme SQL databázu, ale v realite sa tam nachádzalo Mongo (to je veľmi zaujímavý predstaviteľ NoSQL databáz).

Čo sa týka prevádzky aplikácie, očakávame časté volanie „end point-u“ na zoznam hracích dní, ktoré vyberáme z databázy a vraciame klientovi. Každým volaním teda vchádzame do databázy, vyberáme z nej všetky potrebné údaje, formátujeme ich a následne vraciame klientskej aplikácii. Údaje sa musia pravidelne obnovovať – problém však nastáva vtedy, keď prostredníctvom aplikácie sledujú jeden zápas tisícky ľudí, čo môže byť pretavené do situácie, kedy za jednu sekundu príde požiadavka od klientskej aplikácie na zoznam aj 500-krát. To sa samozrejme začne prejavovať práve na výkone, pretože sa zvýši čas, za aký server dokáže vybaviť danú požiadavku. V najhoršom prípade sa môže stať to, že služba bude nedostupná alebo začne time-outovať, s čím sa užívateľská skúsenosť výrazne zníži (pri skupine ľudí, ktorí sledujú slovenskú hokejovú extraligu, je práve toto veľmi nepríjemné).

Otázka je, ako nám vie práve v tomto prípade pomôcť Redis? Jedno z najčastejších využití Redis-u je práve cache-ovanie. Ten sa na serveri nachádza vedľa samotného aplikačného backend-u a aplikácie, prípadne ho vieme spustiť aj na samostatnom serveri (buď ako klasickú inštaláciu alebo dopyt kontajnera). Našu aplikáciu teda vieme upraviť tak, aby sa po príchode požiadavky do serveru najskôr pozrela do Redis-u, či sa tam daný záznam už nenachádza. V prípade, že áno, tak ho aplikácia vráti v odpovedi; naopak v prípade, že nie, tak vyberieme údaje z databázy, naformátujeme ich na požadovaný tvar, uložíme ich do Redis-u a vrátime ako odpoveď klientskej aplikácii.

Platnosť záznamu v Redis-e môžeme nastaviť napríklad na 5 sekúnd  – čas nastavenia platnosti si však môžeme zvoliť podľa svojho vlastného úsudku (dôležité je ale dbať na to, aby tým nenastalo zhoršenie kvality záznamu – ten totiž môže mať nejakú hodnotu aj v závislosti od toho, aký je starý). Keď sa pozrieme na konkrétny prípad zoznamu hracích dní, tak platnosť záznamu môžeme pokojne nastaviť aj na 60 sekúnd – v zásade tým takmer nič neovplyvníme, nakoľko sa dané dáta až tak často nemenia. Ak by sme ale cache-ovali napríklad detail zápasu, tak si musíme dať pozor na to, aby sme nemali oneskorenie v kvalite a aktuálnosti dát (v tomto prípade je vhodné zvoliť len pár sekúnd, vďaka ktorým sa výrazne odľahčí server).

Nastavením pôvodnej platnosti na 5 sekúnd sme však získali jednu veľkú výhodu. Tá pozostáva v tom, že do databázy vstúpime v rámci jednej minúty len 12-krát namiesto 30000-krát, ak počítame s tým, že nám príde v priemere okolo 500 požiadaviek za sekundu. Zvyšné požiadavky budú vybavené z cacheo-vaného zoznamu v Redis-e, kde načítanie záznamu je výrazne lacnejšie a rýchlejšie pre prístup na disku.

 

JS projekty

 

V akých ďalších prípadoch je vhodné použiť Redis?

„queu“ alebo fronty – využitie tam môžeme nájsť hlavne pri riadení / spracovaní údajov, kde vie Redis výrazne uľahčiť prácu (dajú sa tam implementovať napríklad funkcie ako push a pop, a rôzne ich modifikácie vrátane veľmi užitočných funkcií blokovania fronty pri prístupe viacerých klientov)

„counting“, respektíve počítanie úplne čohokoľvek – Redis je veľmi užitočný na zbieranie štatistík, pretože obsahuje set funkcií určených na inkrementáciu a dekrementáciu hodnôt (tie sú využívané často aj pri relačných databázach)

 

Kedy nie je veľmi vhodné použiť Redis? Aké sú riziká pri jeho použití a na čo treba dbať?

Asynchrónny zápis na disk

Redis je vo svojej základnej konfigurácii „in-memory“ úložiskom, teda má dáta uložené v pamäti. Rezistencia údajov na disku je možná až vtedy, keď sa daná funkcia zapne (v niektorých základných konfiguráciach je už teraz rezistencia aktívna). Pri rezistencii je ale potrebné dbať na to, že aj po jej zapnutí prebieha zápis na disk asynchrónne, To znamená, že keď zapisujete dáta do Redis-u, tak nie sú zapisované v rovnakom čase aj na disk (v prípade zlyhania servera teda môžeme stratiť údaje, ktoré neboli zapísané na disku).

 

Používanie Redis-u primárne ako dátové úložisku

Pri tejto voľbe je určite nesmierne potrebné a dôležité zvážiť očakávaný objem údajov. To, že sú všetky uložené v RAM-ke, má veľkú výhodu z hľadiska rýchlosti, avšak z pohľadu potrebnej kapacity a aktuálnych cien za cloud-ové služby / operačnú pamäť treba byť opatrný. Aktuálne je tam veľký nepomer v cenách medzi kapacitou disku a kapacitou RAM-ky.

 

Dizajn aplikácie

Nakoľko je práca s Redis-om v mnohých aspektoch veľmi špecifická, tak je potrebné a vhodné myslieť na jeho vlastnosti a funkcie už pri dizajnovaní aplikácie a to predovšetkým v prípadoch, keď má byť Redis použitý ako „prime register“.

 

Akým chybám sa vyhnúť pri používaní Redis-u?

nedostatočné zabezpečenie ako napríklad nepoužívanie hesla pre prístup k Redis-u alebo otvorenie Redis-u do sveta

príkaz keys – je potrebné brať ohľad na to, že keys je synchrónny príkaz, čo znamená, že v závislosti od počtu záznamov v databáze môže na dlhú dobu zaťažiť server a v tom čase znemožniť  Redis-u obsluhovať akékoľvek ďalšie požiadavky (väčšinou sa však príkaz keys používa len v „debug“ verzii a nie v produkcii – určite je však vždy vhodnejšie používať napríklad príkaz scan)

číslované databázy – v rámci Redis-u je možné pracovať nad viacerými databázami zároveň a prepínať sa medzi nimi, avšak tento spôsob nie je veľmi dobre navrhnutý (databázy sú od seba nedostatočne odizolované) – ak by ste náhodou jednou databázou, ktorá obsahuje veľa záznamov, spustili príkaz keys, tak tým viete odstaviť aj všetky zvyšné databázy, čo napovedá, že zaťaženie na jednu dištanciu je zdieľané – tento problém číslovaných databáz aj samotní autori Redis-u označujú za jednu z najväčších chýb v jeho dizajne a rovnako upozorňujú na to, že pokiaľ chce niekto stavať aplikáciu nad funkciou keys, tak je potrebné brať ohľad na to, ako sa správa

nový „connection“ pre každý „request“ – po správnosti by sa mal udržiavať jeden otvorený „connection“ s využitím pre viacero príkazov namiesto otvárania a zatvárania nových „connections“ (v minulosti bol problém držať jeden otvorený „connection“ pri PHP, avšak v novších verziach sa to už zlepšilo)

hot-key problém – ten vychádza predovšetkým z distribuovaného systému / prostredia – ak by sme v Redis „cluster“ mali jeden kľúč, ku ktorému pristupujeme pomerne často, tak to v podstate znamená, že veľmi často pristupujeme k jednému node-u (tento problém je teda potrebné riešiť už v aplikačnom návrhu a predchádzať tak situácii vzniku „hot-key“)

 

Bezpečnosť

Bezpečnosti v rámci Redis-u je potrebné venovať vysokú pozornosť – veľmi často býva zanedbávaná  a neuvádzaná v „tutorial-och“ alebo dokumentáciach. Redis vo viacmenej každom projekte s veľkou pravdepodobnosťou obsahuje citlivé údaje, ktoré sú „cacheo-vané“ a ktoré nechceme verejne vystavovať. Z toho dôvodu je potrebné Redis chrániť a nejakým spôsobom zabezpečiť. Jedným z prostriedkov, ako to vykonať, je izolované prostredie. Autorizácia prístupu k Redis-u nie je implementovaná na veľmi pokročilej úrovni, preto je veľmi dôležité a možné nastaviť si heslo a nenechávať prístup k Redis-u bez neho. Ideálne však je podporiť bezpečnosť údajov aj izolovaním inštancie a to hlavne od vonkajšieho sveta. Pokiaľ Redis beží spustený na serveri ako klasická aplikácia, tak je dobré obmedziť prístup k port-u (pri Redis-e je to 6379 v nastavení firewall-u). Prístup k Redis-u by teda mal byť umožnený prostredníctvom nejakej serverovej aplikácie, teda by k nemu nemalo byť možné pristupovať priamo (od verzie 3.2 odpovedá Redis pri používaní iných rozhraní chybou). Spôsob zabezpečenia nie je veľmi podporovaný ani tvorcami s prihliadnutím na architektúru aplikácie – tvorcovia väčšmi odporúčajú riešiť zabezpečenie aplikácie práve izoláciou prostredia, teda tým, kde v architektúre aplikácie sa Redis nachádza. Mal by sa nachádzať na mieste, kde nie je ľahko dostupný alebo dosiahnuteľný. Ďalším dôležitým prvkom je aj prístup z „frontend-u“ – „frontend-om“ môže byť v tomto prípade aj klientska aplikácia, ktorá môže nejakým spôsobom pristupovať k Redis-u vzdialenému na serveri (čo tiež nie je vhodná praktika, nakoľko to je v rozpore s izoláciou prostredia). Najudržateľnejšie je preto medzi „frontend“ a Redis postaviť určitý aplikačný „backend“, ktorý zabezpečí komunikáciu medzi nimi.

 

V prípade, že s Redis pracujete alebo sa oň zaujímate, tak Dušan určite odporúča pozrieť si témy ako Redis Cluster alebo distribuované prostredie

 

Sledujte naše aktivity aj na našom Instagram a Facebook profile alebo na LinkedIn.