Ismerje meg a Redis-t egy e-kereskedelmi webhely létrehozásával a Node.js, Express és Redis segítségével

Áttekintés

"Redis"

"Az alkalmazás beállítása"

Gyorsítótár a Redisben

Redis mint NoSQL-dokumentumadatbázis

Munkamenetkezelés a Redis segítségével

"Fennmaradó útvonalak"

"Következtetés"

Áttekintés

Ha ezt olvassa, feltételezem, hogy legalább utánanézett a Redis definíciójának, és gyakorlatiasabb megközelítést keres, hogy megbirkózzon vele. Egyszerűen fogalmazva,

A Redis népszerű választás a gyorsítótárazáshoz, a munkamenet-kezeléshez, a játékokhoz, a ranglistákhoz, a valós idejű elemzésekhez, a térinformatikai adatokhoz, az utazáshoz, a csevegéshez/üzenetküldéshez, a média streaminghez és a pub/sub alkalmazásokhoz.

A Redis a legalkalmasabb a gyors adatlekérésre. Ezt a Redis memórián belüli tárolója éri el. A legtöbb adatbázis tárolása lemezen vagy SSD-n található. Mint ilyen, az adatbázis-műveletek egy oda-vissza utat igényelnek a lemezre. Ezzel szemben a memóriában lévő adatok a szerver RAM-jában találhatók, nem vonatkoznak rájuk ugyanazok a korlátozások, ezredmásodperc alatti válaszidőt biztosítanak, és így sokkal több műveletet támogatnak.

Ennek a bevezető oktatóanyagnak az a célja, hogy gyakorlati megközelítésként szolgáljon a Redis által támogatott egyes adatstruktúrákhoz és műveletekhez. Egy egyszerű e-kereskedelmi webhelyet készítünk a NodeJS és az Express használatával.

Ennek az oktatóanyagnak a hatóköre eredetileg a Redis-szel végzett munkamenet-kezelésre korlátozódott, azonban nyilvánvalóvá vált, hogy a Redis sokoldalúsága kihasználható az alkalmazás legtöbb funkciójának megvalósítására. A Redist a következő minőségben fogjuk használni:

  • Az API válaszok gyorsítótárazása.
  • NoSQL-dokumentum-adatbázisként az alkalmazás felhasználói számára.
  • Munkamenet menedzsment.
  • A felhasználók bevásárlókosarainak tárolása.

A befejezést követően az alkalmazásunkat meglátogató ügyfélnek képesnek kell lennie a következőkre:

  • Tekintse meg az elérhető elemek listáját.
  • Regisztráljon és jelentkezzen be.
  • Tételek hozzáadása és eltávolítása a kosárból; és megtekintheti a kosaruk tartalmát.
  • Végezze el vagy mondja le a vásárlást, közben ürítse ki a kosarát.

Redis

A Redis használatához a következőket telepítjük:

  • Docker: Nyílt platform alkalmazások fejlesztéséhez, szállításához és futtatásához. Redis szerverünket egy Docker-tárolóban fogjuk futtatni.
  • Redis:Nyílt forráskódú kulcsérték tároló, amely adatszerkezet-szerverként működik.
  • RedisInsight: Redis grafikus felhasználói felület az adatok megjelenítéséhez, valamint parancsok végrehajtásához a shell használata nélkül, bár CLI is rendelkezésre áll.

Telepítés

Ugrás a Redis GUI szakaszra, ha már telepítve van a Redis. Docker ismerete nem szükséges. Egyszerűen telepítse a Dockert Ubuntu (1. lépés és 2. lépés), Mac vagy Windows rendszerre. Ezután húzza ki a Redis-képet a Docker Hubból.

docker pull redis

Indítson el egy Redis-tárolót a redis aliassal, amely a --name opcióhoz tartozik. A Docker démon leképezi a tárolót a Redis alapértelmezett portjára a -p jelzővel, 6379, és végül a démon a -d jelzővel indul.

docker run --name redis -p 6379:6379 -d redis

Ellenőrizze, hogy a tároló fut-e:

docker ps

A várt kimenetnek hasonlónak kell lennie:

CONTAINER ID   IMAGE     COMMAND                  CREATED       STATUS              PORTS                                       NAMES
fabcb755ad52   redis     "docker-entrypoint.s…"   10 days ago   Up About a minute   0.0.0.0:6379->6379/tcp, :::6379->6379/tcp   redis

Ha le szeretné állítani, hogy a tároló ne futjon együtt:

docker stop redis

A Redis tároló újraindításához:

docker start redis

Redis GUI

Futtassa a RedisInsight-ot egy Docker-tárolóban a következő parancs végrehajtásával, és várja meg, amíg a letöltés befejeződik:

docker run -v redisinsight:/db -p 8001:8001 redislabs/redisinsight:latest

Győződjön meg arról, hogy az előző lépésben szereplő Redis-példány is fut, majd navigáljon a http://localhost:8001 címre a böngészőjében. Hasonló oldalt kell látnod:

Válassza a I already have a database, majd aConnect to a Redis Database lehetőséget.

Szerezze be a Redis-tároló IP-címét a Host* értékeként a következő parancs futtatásával:

docker container inspect -f "{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}" redis

Ha a Dockertől eltérő más módszert használt a Redis telepítéséhez, használja a localhost értéket a Host* értékeként. Töltse fel a mezőket.

Host*: <IPAddress>
Port*: 6379
Name*: <EnterAName>

A létrehozott adatbázist látnia kell a kezdőlapon.

Az adatbázis kiválasztásával áttekintést kapunk a Redis példányról. Lépjen a Browser elemre a BROWSE alatt, ahol megtekintheti a tárolt értékeket. A Redis parancsokat a CLI lapon is végrehajthatjuk.

Az alkalmazás telepítése

Beállítás

Feltételezem, hogy már telepítve van a NodeJS. Klónozza a következő repository-t, cd a könyvtárba, és telepítse a függőségeket. A „PugJS”-t használjuk sablonmotorként.

Ez az alkalmazás váza. A vonatkozó kódot és magyarázatot az alábbiakban ismertetjük.

npm i

Az alkalmazás elindításához:

npm start

A http://localhost:3000 címre navigálva az alkalmazás kezdőlapjára jutunk. Az oktatóanyag hatókörének korlátozása érdekében a valódi e-kereskedelmi webhelyek bonyolultságából sokat kihagytak.

3 nézetünk van. Ott van a kezdőlap, ahol az elemek megjelennek. A felhasználók oldalán létrehozhatunk felhasználót, megtekinthetjük a nemrég létrehozott felhasználókat, és bármely felhasználóként bejelentkezhetünk. Végül megtekinthetjük a kosár tartalmát és folytathatjuk a rendelés teljesítését vagy törlését.

A munkamenetadatok tárolásához az alkalmazás kezdetben a express-session alapértelmezett munkamenet-tárolójára – MemoryStore – támaszkodik, amely a fejlesztő szerint

szándékosan nem termelési környezethez készült. A legtöbb esetben kiszivárogtatja a memóriát, nem lép túl egyetlen folyamaton, és hibakeresésre és fejlesztésre szolgál.

A munkamenet-kezelés részben kitérünk arra, hogyan tárolhatjuk a munkamenetadatokat a Redisben.

A munkamenet köztes szoftver engedélyezése a app.js fájlban. A express-session megkövetelése és hozzáadása a köztes szoftverek tömbjéhez. Engedélyezzük a flash üzenetküldést is. A flash üzenetküldés beállításához szerkesszük a köztes szoftver funkciót is, amely beállítja a cartCount tulajdonságot a res.locals-ban.

Ha az alkalmazás már fut, írja be: rs és ⏎.

Redis csatlakoztatása

A Redis klienst a ioredis használatával inicializáljuk. Adja hozzá a következőt a app.js-hoz.

A Redis-kliensobjektumot tulajdonságként a config-ben mentve elérhetővé tesszük az egész alkalmazásban. Indítsa újra az alkalmazást.

Gyorsítótárazás

Üzletünk készlete jelenleg üres. Külső szolgáltatást fogunk kérni az áruház termékeiről. A „Fake Store API”-t használjuk a leltár létrehozásához és az eredmények gyorsítótárazásához a Redisben, csökkentve ezzel az API-hoz intézett kérések számát.

Minden elem Redis Hash adattípusként kerül tárolásra. A hashek olyan térképek, amelyek értékekkel társított mezőkből állnak, és alkalmasak objektumok ábrázolására. A kivonatok a Redisben így nézhetnek ki:

"object-type:id" field1 value1 field2 value2 ... fieldN valueN

Az első bejegyzés a hash kulcsát jelenti, a benne lévő mezőkkel és értékekkel. Pl. A 100 cikkszámú tétel a Redisben a következőképpen jeleníthető meg:

"item:100" name "Jordan Series 0.1" price 115.00 ...

"Íme" a Redis által támogatott egyéb adattípusok áttekintése.

A tételazonosítókat is egy külön listában indexeljük. Egy TTL (élettartam) minden tételhez és a cikkazonosítók listája is be lesz állítva. A kulcsok lejárnak, amikor a TTL letelik, és automatikusan törlődnek a Redisből. A TTL-t 1 órára állítjuk a bemutatóra.

Adja hozzá a következőket a data/items.js-hez, és indítsa újra a szervert.

rs

A axios HTTP kérések benyújtására szolgál. A dayjs egy dátum-idő könyvtár, amelyet az időhöz kapcsolódó információk megjelenítésére használunk. A Items egy olyan függvény, amely egy config objektumot vesz argumentumként. A config objektum tartalmazza a Redis kliens objektumot. A Items függvény a data/index.js fájlban lesz meghívva és exportálva az útvonalakba. A ioredis visszahívásokkal és ígéretekkel működik. Ígéreteket használtunk, ezért a async/await-et egy try…catch blokkon belül használjuk. A ioredis metódusok az azonos nevű Redis-parancsokhoz vannak leképezve. Az összes használt parancsot megtekintheti itt.

Először ellenőrizzük, hogy a cikkazonosítók listájához tartozó item:itemList kulcs még mindig létezik-e, vagy lejárt-e. Ha lejárt, a Redis EXISTS parancsára a válasz 0, amely után egy kérés érkezik az API-hoz. A válasz elemobjektumok tömbje. A Redis tranzakciói lehetővé teszik egy parancscsoport egyetlen lépésben történő végrehajtását. A tranzakció úgy jön létre, hogy meghívja a MULTI parancsot az ügyfélen, a parancsokat sorba állítja a tranzakción, és végül végrehajtja azokat a EXEC paranccsal. A Items függvényben a transaction az API-válasz beérkezése után jön létre. Iterálunk a tömbön, a strukturáló hozzárendelési szintaxis használatával kicsomagoljuk a tulajdonságokat az egyes item-ből, és mindegyikhez sorba állítjuk a következő parancsokat:

  • HSET 👉🏾Kivonatolási módszer, amely 2 argumentumot, a hash kulcsát (item:id) és a mező-érték párok egy objektumát foglalja magában, amelyet a hashben tárolnak.
  • EXPIRE 👉🏾A TTL értéket állítja be másodpercekben az argumentumként megadott kulcson.
  • RPUSH 👉🏾Lista módszer, amely értékeket szúr be a lista végére. A lista létrejön, ha nem létezik.

Az item:itemList kulcshoz tartozó EXPIRE parancs is sorba kerül az összes elem feldolgozása után, végül meghívja az EXEC parancsot a transaction-on, és a műveletek egymás után hajtódnak végre. A tranzakciók atomi azaz vagy az összes parancsot feldolgozzák, vagy egyiket sem. Az if blokk nem hajtódik végre, ha a EXISTS parancs válasza 1 .

Meghívjuk a TTL parancsot egy kulcson, hogy idővel kapcsolatos információkat kapjunk és jelenítsünk meg adatainkkal kapcsolatban.

A Items függvény alapértelmezett művelete az elemek lekérése a Redisből. Először megkapjuk az összes elemazonosítót a item:itemList-től a LRANGE listamódszerrel, amely elfogad egy listakulcsot, egy start- és egy stop indexet. A -1 a lista utolsó eleme. Létrehozunk egy másik tranzakciót, itemPipeline, és sorba állítunk HGETALL parancsokat minden egyes tételazonosítóhoz. A HGETALL lekéri a megadott kulcson tárolt hash összes mezőjét és értékét. A tranzakció során a EXEC parancs kerül meghívásra. Az eredmény egy tömb tömbje néhány null értékkel, amelyeket flat és filter tömbmódszerekkel szűrünk ki.

Az API kérés és a Redis műveletek console.time() hívásokba vannak csomagolva, hogy képet kapjunk arról, mennyi ideig tartanak az egyes műveletek.

A routes/index.js belsejében importáljuk a Items elemet, és rendereljük a kezdőlapon lévő elemeket. Adja hozzá a következőket.

Indítsa újra a szervert. Látnia kell a kezdőlapon megjelenő elemeket. A tárolt kivonatokat a RedisInsight Browserlapján is megjeleníthetjük.

A terminálban a különböző műveletek idővel kapcsolatos információinak láthatónak kell lenniük. Megjegyzendő, hogy mennyi időbe telik az adatok lekérése az API-ból (querying-api ), összehasonlítva ugyanazoknak az adatoknak a Redisből való lekérésével (retrieved-from-cache ).

Dokumentum adatbázis

Definíció szerint a Redis egy NoSQL adatbázis, és a MongoDB-hez hasonló módon dokumentumokként tárolhatjuk az adatokat. Bár ésszerűbb lenne a felhasználókat kivonatként menteni, JSON-karakterláncként mentjük őket a Redis képességeinek bemutatása céljából. A Felhasználók kezelése oldalon található űrlap kitöltésekor a rendszer egy POST kérést küld a /usersútvonalra. Határozzuk meg az útvonalat. Szerkessze a következőket itt: routes/users.js.

A Redis ügyfélobjektum importálása és kicsomagolása a config objektumból. Az űrlapmezők értékeit a rendszer a kérés törzséből elemzi. A bcrypt és a crypto jelszó kivonatolásra és felhasználói azonosító generálására szolgál. Felhasználó hozzáadásához létrehozunk egy tranzakciót, majd sorba állítjuk a következő parancsokat:

  • SET 👉🏾beállít egy kulcsot a második argumentumként megadott karakterlánc-érték tárolására.
  • LPUSH 👉🏾a felhasználói azonosítót a user:userList elé fűzi.
  • GET 👉🏾egy kulcs értékét adja vissza

A parancsok EXEC-vel kerülnek lebonyolításra, és az eredményt a válaszból nyerik ki. A RedisInsightban megtekinthetjük a regisztrált felhasználókat.

A regisztrált felhasználók listájának megjelenítéséhez a rendszer lekéri a felhasználói adatokat a Redistől, amikor egy GET kérést küldenek a /users címre. Szerkessze az útvonalat itt: routes/users.js.

Hasonlóan az összes elem lekéréséhez, a felhasználói azonosítók listáját a LRANGE segítségével kapjuk meg. A rendszer végrehajt egy tranzakciót, amely GET parancsot tartalmaz a listán lévő összes felhasználói azonosító kulcshoz. A felhasználókat a rendszer elemzi a válaszból, és a users nézetben jeleníti meg.

Munkamenet menedzsment

Ha a munkamenetadatok továbbra is a MemoryStore-ben vannak tárolva, az alkalmazás nem tud egyszerre több felhasználói munkamenetet támogatni, és ezek az adatok csak a munkamenet időtartama alatt használhatók. A express-session-cal kompatibilis külső tároló használata lehetővé teszi a folyamatos tárolást és a több munkamenetet.

A connect-redis külső munkamenet-tárolást biztosít egy Express-alkalmazáshoz egy meglévő Redis-kliens használatával. Létrehozunk egy connect-redis példányt a session köztes szoftverrel, mint argumentum. A Redis kliens ezután átkerül a session köztes szoftverhez.

A connect-redis megkövetelése a app.js-ben, és szerkessze a session bejegyzést a middlewares tömbben.

A kiszolgáló újraindításakor a munkamenetadatok most JSON-karakterláncként kulcs-érték párban kerülnek mentésre a Redisben.

Munkamenet adatok tárolása

A felhasználói adatok is tárolásra kerülnek a munkamenet adatainak részeként. Az egyszerűség kedvéért a felhasználói bejelentkezést szimuláljuk úgy, hogy rákattintunk egy felhasználóra a felhasználók táblázatában. A kiválasztott felhasználói azonosító munkamenet-változóként kerül tárolásra, és a megfelelő felhasználói adatok a Redis-ből egy köztes szoftver funkcióban kerülnek lekérésre. A jelenleg bejelentkezett felhasználói adatok elérhetőek az alkalmazásban a res.locals címen keresztül.

A felhasználó bejelentkezési útvonalát közvetlenül a felhasználó létrehozási útvonala alatt határozzuk meg a routes/users.js-ban.

Valósítsuk meg a felhasználói lekérést a app.js-ben. Adja hozzá a következőket a köztes szoftver funkcióhoz, ahol beállítjuk a flash üzenetküldést és a kezdeti cartCount-t.

Most már tudnunk kell váltani a felhasználók között. Ennek az oktatóanyagnak az elején a munkamenet köztes szoftverének engedélyezésekor a cookie maxAge tulajdonsága 1 órára volt beállítva, ami után a Redisben a munkamenetkulcs TTL értékét is ugyanarra az időpontra állítja be, amely után a munkamenet lejár, és a felhasználó kijelentkezett.

A bevásárlókosár mentése

Engedélyezzük a bejelentkezett felhasználóknak a vásárlást. Engedélyezze a Vásárlás most funkciót az útvonal szerkesztésével a routes/index.js helyen.

A felhasználó átirányítja a kezdőlapra, ha nincs bejelentkezve, vagy egy nem létező elemet kérdez le. Az aktuális felhasználói azonosító a res.locals objektumból származik. A kosár kulcsának részeként lesz használva. Az elemazonosító az útvonal paramétere az URL-ben.

A kosár adatait kivonatként menti a rendszer cart:userID kulcsként, mindegyik item:itemID mezőként és a tételek számát értékként. A Redis HINCRBY parancsa 3 argumentumot vesz fel, a kulcsot, egy mezőt és a mező értékét. Ha a kulcs nem létezik, akkor az alapértelmezett 0 értékkel jön létre.

A kosárban lévő tételek a Redisben vannak elmentve, de ez nem jelenik meg a kezelőfelületen. Ehhez lekérjük a tételazonosítókat a felhasználó kosarából, összeszámoljuk az értékeket, és frissítjük a res.locals.cartCount értéket a köztes szoftver funkciójában, ahol inicializáltuk. A /users/:userId/cart útvonalon pedig a Redis tényleges tételeit fogjuk megjeleníteni.

Adja hozzá a következőket a app.js köztes szoftver függvényéhez, a if (req.session.userId) blokkon belül.

Szerkesszük az /users/:userId/cartútvonalata routes/users.js-ben, hogy megkapjuk a tényleges elemeket.

A felhasználói azonosítót az útvonalparaméterből elemezzük, ellenőrizzük, hogy az aktuális felhasználó hozzáfér-e az adott kosárhoz. Iterálunk a res.locals.cartData tömbön, lekérve a kapcsolódó cikkinformációkat a kosárból való számláláson kívül, és az adatokat a cartData tömbbe toljuk. A rendszer a teljes árat is kiszámítja és megjeleníti a cart nézetben. A kosár adatai a RedisInsightban tekinthetők meg.

A fennmaradó útvonalak meghatározása

Kosár tételek hozzáadása és eltávolítása

Adjunk funkcionalitást a kosárban található ➕️ és ➖️ gombokhoz. Szerkessze a routes/users.js-on belüli útvonalakat.

A felhasználói azonosító és az elemazonosító útvonalparaméterek elemzése az URL-ből történik, és a itemId mező értéke a cart:userId kulcson tárolt hashben vagy nő, vagy csökken. Ugyanazt a parancsot használjuk, mint amikor az tételek először kerülnek hozzáadásra a kosárhoz — HINCRBY . A Redis parancs az érték hozzáadására és csökkentésére ugyanaz, kivéve az utolsó argumentumot – az értéket, amellyel a mezőt növelni kell; 1 növelni, -1 pedig csökkenteni. Most már képesnek kell lennie a kosárba tételek hozzáadására és eltávolítására.

A cikkszám csökkentésével azonban a szám 0-ra és az alá csökkenhet. Redis nem tudja, hogy a kosár tételei csak pozitív egész számok lehetnek. Ezt a munkamenet köztes szoftverben fogjuk kezelni, ahol a kosárban lévő cikkazonosítók listájának lekérése után, ha egy itemId mező értéke kisebb, mint 1, akkor a HDEL paranccsal töröljük a kosárból, amely törli a mezőt a hashből. a megadott kulcson tárolva. Szerkessze a köztes szoftver funkciót itt: app.js.

A kosár feldolgozása

Utánozhatjuk azt, ami egy valódi bevásárlókosárban történne. Ha a vásárlás befejeződik, a rendelési adatok valószínűleg egy robusztusabb adatbázisba kerülnek. Akár a rendelést, akár lemondja, a kosár kiürül. Szerkessze a következő útvonalakat itt: routes/users.js.

A DEL parancs a kosár ürítésére szolgál. Eltávolítja a megadott kulcsot az áruházból.

Felhasználó törlése

Végül engedélyezzük a 🗑 gombot a Felhasználók kezelése oldalon. Szerkessze a felhasználói útvonal törlését itt: routes/index.js.

Létrehozunk egy tranzakciót, és sorba állítjuk rajta a törlési parancsokat, mielőtt végrehajtanánk azokat. A DEL parancs elfogadja a kulcsok listáját, hogy eltávolítsa, ebben az esetben a felhasználó kosarát és adatait. A felhasználó azonosítója törlődik a user:userList-ből a LREM paranccsal, amely 3 argumentumot fogad el, a lista kulcsát, a számlálót (a törölni kívánt előfordulások számát) és a listából eltávolítandó elemet. Ha a számláló értéke 0, akkor az adott elem minden előfordulása törlődik a listáról.

Következtetés

A Redis egy sokoldalú tárolószerver számos felhasználási esettel. Különösen a gyorsítótárazási technológiai környezetben tűnik ki, jelentősen javítva az alkalmazások teljesítményét. A rendelkezésre álló különböző adatstruktúrák hatékony módokat biztosítanak az adatok mentésére és lekérdezésére, amelyek nem érhetők el egy vanília kulcsérték-gyorsítótárral.

Ennek a cikknek nem célja, hogy a Redist az adatbázisok TVA-jaként javasolja; annak vannak korlátai. Bár a Redis dokumentumadatbázist is használtuk, hiányzik a beépített titkosítás; nem rendelkezik szerepkör alapú fiókvezérléssel; és fájdalmas lehet a telepítés nagyszabású felhőalapú telepítéseknél. Ezenkívül a jobb teljesítmény áldozata a megnövekedett memóriahasználat, amely majdnem kétszer annyi memóriát használ, mint amennyit ugyanazok az adatok a lemezen foglalnának el.

Remélhetőleg ez hasznos alapozó volt a Redisben. Köszönöm, hogy a végéig elkészítetted. Javaslatokat és fejlesztéseket várunk a megjegyzésekben. Boldog hackelést 👍🏾️.

További tartalom: «plainenglish.io