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
👉🏾ATTL
é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 Browser
lapjá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 auser: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