# DFU 07 ## Redis In-Memory Database --- ## Introduktion & grundlæggende koncepter ---- ### Hvad er Redis? - **Redis** står for **Re**mote **Di**ctionary **S**erver - **In-memory database**, altså gemmes data i RAM og ikke på disk (default behaviour) - Dette gør, at Redis er ekstremt hurtig til læse- og skriveoperationer - Operation måles typisk i mikrosekunder - En typisk GET-operation tager under 1 millisekund - **Key-Value Store**, hvor data gemmes som nøgle-værdi par, ergo er der ingen tabeller eller joins i traditionel forstand - **NoSQL**, hvilket betyder, at det ikke bruger SQL som forespørgselssprog ---- ### Hvad bruges Redis til? 1. Caching - Gemme resultater fra "dyre" database queries - Cache HTML-fragmenter eller hele sider - API-response caching - Eksempel: - En webshop cacher productioninformation i 5 minutter for at reducere belastning på hoveddatabasen ---- ### Hvad bruges Redis til? (fortsat) 2. Session Storage - Gemme bruger-sessions i web applikationer - Hurtig adgang til session-data på tværs af servere - Automatisk expiration af sessions med TTL - Eksempel: - ItsLearning kunne bruge det til at håndtere login og sikre at du er logget ud efter 18 minutter ---- ### Hvad bruges Redis til? (fortsat) 3. Real-time analytics og counters - Tælle page views, likes, downloads i real-time - Leaderboards og ranglister - Rate limiting (e.g. max 100 API-kald pr. time) - Eksempel: - En social media apps "trending topics" opdateres sekund for sekund ---- ### Hvad bruges Redis til? (fortsat) 4. Message queues og pub/sub - Kommunikation mellem microservices (ligesom RabbitMQ) - Real-time notifikationer - Chat systemer - Eksempel: - En notification-service der sender beskeder til alle studerende i tilfælde af en nødsituation ---- 5. Geospatial data - Hurtig opslag af geografiske data - Location-based services, e.g. finde venner i nærheden - Eksempel: - Wolt, tracking af chaufførerens position i real-time ---- ### Hvorfor vælge Redis? - **Performance**, 100.000+ operationer per sekund er ikke usædvanligt - **Simplicity**, Enkelt API, let at komme i gang med - **Flexibility**, mange datatyper og use cases - **Atomic operations**, indbygget support for atomiske operationer uden race conditions (e.g. sikre at brugere ikke kan købe udsolgte varer) - **Persistence options**, selvom det er in-memory, kan Redis konfigureres til at gemme data på disk ---- ### Hvornår skal man ikke bruge Redis? - Som primær database for kritiske data der ikke må gå tabt (med mindre persistence er korrekt konfigureret) - Når datasættet er meget større ened tilgængelig RAM - Når du har brug for komplekse relationer og og joins - Når du har brug for ACID-transaktioner på tværs af mange operationer ---- ### In-memory vs. Disk-based databaser
- Traditionelle databaser - Data gemmes på HDD eller SSD - Disk I/O er typisk største flaskehals - Hastighed (afhængig af disk og RAID): - Læse: 1-20 ms - Skrive: 5-50 ms - Kapacitet: TB til PB+ - Billig at skalere
- In-memory databaser (som Redis) - Data gemmes i RAM - RAM er meget hurtigere end disk - Hastighed: - Læse: <1 ms - Skrive: <1 ms - Kapacitet: GB til TB (afhængig af serverens RAM) - Dyrere at skalere
---- ### Redis og persistence - RDB (Redis Database Backup) - Laver periodiske snapshots til disk (konfigureres) - Hvis serveren crasher, mister du max konfigureret periode - Hurtig at loade ved genstart - AOF (Append Only File) - Logger hver skrive-opretation til disk - Kan konfigureres til at synkronisere hvert sekund eller oftere - Mere data-sikkerd, men langsommere - Hybrid tilgang ```ini [] # redis.conf save 900 1 # Gem efter 900 sek hvis mindst 1 ændring save 300 10 # Gem efter 300 sek hvis mindst 10 ændringer appendonly yes # Aktivér AOF ``` ---- ### Hybrid relationel og in-memory arkitektur - Brug Redis som cache foran en relationel database - Hurtige læseoperationer fra Redis - Skriveoperationer går til den relationelle database - Læseoperation loades til Redis ved cache-miss ---- ### Redis Cache eksempel
- Client laver en forespørgsel til serveren - Serveren tjekker først Redis cache for data - Hvis data findes i cache (cache hit), returneres det med det samme - Hvis data ikke findes i cache (cache miss), hentes det fra den relationelle database - Data gemmes i Redis cache for fremtidige forespørgsler
--- ## Datatyper og kommandoer ---- ### Redis' 5 fundamentale datatyper | Datatype | Beskrivelse | | :------- | :---------- | | String | Simpel tekst eller binær data | | List | En ordnet samling af strings | | Hash | En samling af key-value par (som en JSON objekt) | | Set | En uordnet samling af unikke strings | | Sorted Set | En uordnet samling af unikke strings med en score | ---- ### Karakteristika om keys - Keys er altid strings - Keys er case-sensitive - Keys kan indeholde specialtegn - Anbefalet max længde for en key er 256 bytes ---- ### Strings
Hvad er det? - Den mest basale datatype - Kan indeholde tekst, tal, binær data (billeder, serialiserede objekter osv.) - Max størrelse er 512 MB
Typiske use cases: - Simple værdier (navn, email) - Counters (page views, likes) - Cache af JSON/XML/HTML
---- ### Strings basis kommandoer ``` SET favoritColor "#ff1493" GET favoritColor SET user:1000:name "Alice" GET user:1000:name GETSET user:1000:name "Bob" # Returnerer gammel værdi og sætter ny DEL user:1000:name ``` ---- ### Strings, numeriske operationer ``` SET page:views 0 INCR page:views INCRBY page:views 10 DECR page:views DECRBY page:views 5 GET page:views ``` ---- ### TTL (Time To Live) ``` SET cache.page:/ "..." EX 300 ``` - `EX` aka expire, sætter en TTL i sekunder e.g. 300 sekunder ---- ### Teste det sammen - Starte Redis Docker composen - Teste kommandoer med Redis Insight ---- ### Lists
Hvad er det? - En ordnet samling af strings - Tillader duplikater - Implementeret som en dobbeltkædet liste - Hurtig insert/delete i begge ender - Kan bruges som stack (LIFO) eller queue (FIFO)
Typiske use cases: - Activity feeds (e.g. seneste tweets) - Task queues - Seneste besøgte produkter - Undo/redo funktionalitet
---- ### Lists basis kommandoer: INSERT ``` # Push til venstre (start af liste) LPUSH myDay "Brush teeth" LPUSH myDay "Wake up" # placeret før "Brush teeth" RPUSH myDay "Go to work" # placeret i slutningen LPOP myDay # Fjerner og returnerer "Wake up" RPOP myDay # Fjerner og returnerer "Go to work" ``` - `#` ignorres som kommentarer af Redis CLI - Det skal nævnes at kommentarer ikke er en del af Redis og det skal derfor være en fuld linje og ikke i forløngelse som jeg gør ---- ### Lists basis kommandoer: READ ``` LRANGE myDay 0 -1 # Henter alle elementer (0 til sidste) LRANGE myDay 0 1 # Henter første to elementer LRANGE myDay 1 1 # Henter andet element LLEN myDay # Antal elementer i listen ``` ---- ### Øvelse 5 min. 1. Opret en liste "shopping:list" med 5 ting du skal købe 2. Fjern den første ting fra listen 3. Tilføj en ny ting til slutningen 4. Vis de første 3 ting på listen 5. Hvor kan man bruge expire i en liste -- Hvor ville vi bruge en liste i en rigtig applikation? ---- ### Hashes
Hvad er det? - Key-valye maps inden i en Redis key - Perfekt til at repræsentere objekter - Mere effektiv end multiple strings - Max 4 milliarder felter per hash (er det ikke nok brug en anden database)
Typiske use cases: - Bruger-profiler - Produkt-information - Session data med flere felter - Indstillinger og konfigurationer
---- ### Hashes basis kommandoer: INSERT/UPDATE ``` [] HSET users:313 name "Albert Einstein" HSET users:313 dob "14 March 1879" HSET users:313 city "Ulm" HMSET users:42 name "Author Dent" dob "11 February 1952" city "Cambridge" HGET users:42 name HGET users:414 name dob city HVALS users:42 # Alle værdier i hashen HGETALL users:42 # Alle felter og værdier HKEYS users:42 # Alle keys i hashen HLEN users:42 # Antal felter i hashen HEXISTS users:42 name # Tjekker om feltet "name" findes HDEL users:42 dob # Sletter feltet "dob" ``` ---- ### Øvelse 5 min. 1. Opret en bruger-profil med navn, email og by 2. Tilføj et "points" felt med værdi 0 3. Increment points med 100 4. Hent brugerens email 5. Vis hele profilen 6. Slet "by" feltet ---- ### Sets
Hvad er det? - Uordnede samlinger af unikke strings - Ingen dupletter (automatisk håndteret) - Hurtig membership check (om en given værdi findes i sættet)
Typiske use cases: - Tags på artikler - Unikke besøgende - Online brugere - Relations
---- ### Sets basis kommandoer: INSERT/DELETE ``` # Tilføj medlemmer SADD tags:articles:1 "redis" SADD tags:articles:1 "database" SADD tags:articles:1 "cache" SADD tags:articles:1 "redis" # Ignoreres (allerede i set) # Hent alle artikler SMEMBERS tags:articles:1 # Tjek medlemskab SISMEMBER tags:articles:1 "redis" # Antal artikler SCARD tags:articles:1 ``` ---- ### Øvelse 5 min. 1. Opret et sæt med navne på programmeringssprog du kender 2. Tilføj et nyt sprog 3. Tjek om "Python" er i sættet 4. Vis alle sprog i sættet 5. Tilføj et sprog der ikke findes 6. Slet det forkerte sprog ---- ### Sorted Sets (ZSets) - rangerede collections
Hvad er det? - Ligesom Sets, men hvert medlem har en score (nummer) - Automatisk sorteret efter score - Hurtig adgang til top-N elementer
Typiske use cases: - Leaderboards (highscores) - Priority queues - Tidsbaserede data - Auto-complete suggestions
---- ### Sorted Sets basis kommandoer: INSERT/UPDATE ``` [] # Tilføj medlemmer med scores ZADD leaderboard 100 "alice" ZADD leaderboard 85 "bob" ZADD leaderboard 92 "charlie" # Hent alt (laveste til højeste) ZRANGE leaderboard 0 -1 WITHSCORES # Hent top 2 (højeste til laveste) ZREVRANGE leaderboard 0 1 WITHSCORES ZADD spil:points 50 "player:123" # Increment score ZINCRBY spil:points 10 "player:123" # Nu 60 # Hent score ZSCORE spil:points "player:123" # 60 # Hent rank (position) ZRANK spil:points "player:123" # (0 hvis højeste) # Reverse rank (fra toppen) ZREVRANK spil:points "player:123" # 0 (hvis laveste) ``` ---- ### Sammenligng af datatyper | Datatype | Ordnet? | Dupletter? | Use Case | | :------- | :------ | :--------- | :------- | | String | N/A | N/A | Simple værdier, cache, counters | | List | Ja | Ja | Activity feeds, task queues | | Hash | N/A | N/A | Bruger-profiler, produkt-info | | Set | Nej | Nej | Tags, unikke besøgende | | Sorted Set | Ja (efter score) | Nej | Leaderboards, priority queues | --- ## Redis Pub/Sub ---- ### Hvad er Pub/Sub?
En messsagin-arkitektur hvor: - **Publishers** sender beskeder til channels - **Subscribers** lytter på channels - Publishers og subscribers kender ikke hinanden
Real-world analogi: - Radio/TV-stationer = publisher - Lyttere/seere = Subscribers - FM-frekvenser = channels
---- ### Fire-and-forget (Vigtig begrænsning) - Hvis INGEN subscribers lytter: Beskeden forsvinder - Beskeder gemmes IKKE - Ingen message history - Ingen garantier for levering ---- ### Performance og skalering Redis Pub/Sub er hurtig - Millioner af beskeder per sekund - Tusindvis af samtidige subscribers - Lav latency (under 1 ms i lokale netværk) ---- ### Pub/Sub vs. Message Queues | Feature | Pub/Sub | Message Queue | | :------ | :------ | :------------ | | Decoupling | Høj | Høj | | Message Persistence | Nej | Ja | | Delivery Guarantee | Nej | Ja (ofte) | | Scalability | Høj | Høj | | Use Cases | Real-time notifikationer, chat | Task queues, job processing | | Complexity | Lav | Høj | | Examples | Redis Pub/Sub, MQTT | RabbitMQ, Kafka | ---- ### Pub/Sub kommandoer ``` # Publisher PUBLISH news.sports "Team A won the match!" # Subscriber SUBSCRIBE news.sports news.weather # Unsubscribe UNSUBSCRIBE news.sports ``` --- ### Større øvelse [https://ucl.kjc.dk/dfu/dfu-07-redis-exercise.html](/dfu/dfu-07-redis-exercise.html)