Caching
Das Zwischenspeichern von häufig angefragten Daten oder Berechnungsergebnissen, um wiederholte Anfragen schneller und günstiger zu beantworten.
Eine extrem schnelle In-Memory-Datenbank, die als Cache, Message Broker und Session Store eingesetzt wird – unverzichtbar für performante Anwendungen.
Redis ist eine In-Memory-Datenbank – alle Daten liegen im RAM statt auf der Festplatte. Das macht Redis extrem schnell: Microsekunden statt Millisekunden.
Warum ist das wichtig?
Ohne Cache:
User → API → Datenbank (50ms) → API → User
↑
Jedes Mal
Mit Redis Cache:
User → API → Redis (0.5ms) → API → User
↑
Aus dem RAM
Datenbank nur bei Cache-Miss
Redis-Datenstrukturen:
| Typ | Beschreibung | Use Case |
|---|---|---|
| String | Einfacher Wert | Cache, Counter |
| List | Geordnete Liste | Message Queue, Timeline |
| Set | Ungeordnete Menge | Tags, Unique Visitors |
| Hash | Key-Value in Key | User-Profile, Objekte |
| Sorted Set | Set mit Score | Leaderboards, Rankings |
| Stream | Event Log | Event Sourcing |
Beispiel – Caching:
# Ohne Cache: 50ms Datenbank-Query
SELECT * FROM users WHERE id = 123;
# Mit Redis: 0.5ms
GET user:123
→ Cache Hit: Daten sofort
→ Cache Miss: DB-Query, dann SET user:123
Strings:
SET user:123:name "Max"
GET user:123:name
→ "Max"
INCR page:views
→ 1, 2, 3, ... (atomar)
SETEX session:abc 3600 "user_data"
→ Läuft nach 1 Stunde ab
Hashes:
HSET user:123 name "Max" email "max@example.com"
HGET user:123 name
→ "Max"
HGETALL user:123
→ {"name": "Max", "email": "max@example.com"}
Sorted Sets (Leaderboards):
ZADD leaderboard 1000 "player1"
ZADD leaderboard 1500 "player2"
ZADD leaderboard 800 "player3"
ZREVRANGE leaderboard 0 2 WITHSCORES
→ 1) "player2" 2) "1500"
3) "player1" 4) "1000"
5) "player3" 6) "800"
Cache-Aside (Lazy Loading):
def get_user(user_id):
# 1. Cache prüfen
cached = redis.get(f"user:{user_id}")
if cached:
return json.loads(cached)
# 2. Cache Miss: DB-Query
user = db.query(f"SELECT * FROM users WHERE id = {user_id}")
# 3. In Cache schreiben
redis.setex(f"user:{user_id}", 3600, json.dumps(user))
return user
Write-Through:
def update_user(user_id, data):
# 1. DB updaten
db.update(user_id, data)
# 2. Cache updaten
redis.setex(f"user:{user_id}", 3600, json.dumps(data))
Cache Invalidation:
def delete_user(user_id):
db.delete(user_id)
redis.delete(f"user:{user_id}") # Cache invalidieren
def is_rate_limited(user_id, limit=100, window=60):
key = f"ratelimit:{user_id}"
current = redis.incr(key)
if current == 1:
redis.expire(key, window) # 60 Sekunden
return current > limit
# Publisher
redis.publish("notifications", json.dumps({
"user_id": 123,
"message": "Neue Nachricht"
}))
# Subscriber
pubsub = redis.pubsub()
pubsub.subscribe("notifications")
for message in pubsub.listen():
handle_notification(message)
| Option | Beschreibung | Trade-off |
|---|---|---|
| Keine | Nur RAM | Schnellste, Datenverlust bei Crash |
| RDB | Periodische Snapshots | Gut für Backups, Datenverlust möglich |
| AOF | Jede Operation loggen | Sicherer, etwas langsamer |
| RDB + AOF | Beides | Beste Sicherheit |
Für Skalierung über einen Server hinaus:
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Master 1│ │ Master 2│ │ Master 3│
│ Slots │ │ Slots │ │ Slots │
│ 0-5460 │ │5461-10922│ │10923-16383│
└────┬────┘ └────┬────┘ └────┬────┘
│ │ │
┌────▼────┐ ┌────▼────┐ ┌────▼────┐
│ Replica │ │ Replica │ │ Replica │
└─────────┘ └─────────┘ └─────────┘
Keys werden auf Slots verteilt (Hash-basiert).
Redis ist wie ein Notizblock auf deinem Schreibtisch: Viel schneller als der Aktenschrank (Datenbank), aber begrenzt im Platz. Für häufig gebrauchte Infos ideal – für alles andere nutzt du weiterhin den Schrank.
In-Memory: Daten im RAM statt auf Festplatte – extrem schnell
Vielseitig: Cache, Session Store, Message Queue, Leaderboards
Datenstrukturen: Strings, Lists, Sets, Hashes, Sorted Sets
Caching
Datenbank-Abfragen cachen für schnellere Response-Zeiten
Session Management
User-Sessions in verteilten Systemen speichern
Rate Limiting
API-Anfragen pro User/IP begrenzen
Real-Time Leaderboards
Sorted Sets für Gaming-Ranglisten
Für häufig gelesene Daten, die sich selten ändern. Als Cache vor der Datenbank, nicht als Ersatz. Für Echtzeit-Features wie Leaderboards, Counters, Sessions.
Standardmäßig ja (In-Memory). Redis bietet aber Persistenz-Optionen: RDB (Snapshots) und AOF (Append-Only File). Für kritische Daten aktivieren.
Redis hat mehr Features (Datenstrukturen, Persistenz, Pub/Sub). Memcached ist simpler und manchmal schneller für reines Caching. Redis ist meist die bessere Wahl.
Abhängig von Datenmenge. Faustregel: 2x die Datengröße (für Overhead und Peaks). Monitoring ist wichtig – Redis wird langsam wenn RAM voll.