Redis ist ein In-Memory-Datenstruktur-Server. Er wird für Caching, Session-Storage, Message-Queues und Echtzeit-Analysen eingesetzt.
Redis-Einsatzgebiete
Typische Anwendungen
- Datenbank-Cache
- Session-Storage
- Rate Limiting
- Leaderboards
- Pub/Sub Messaging
- Job Queues
- Echtzeit-AnalyticsDatenstrukturen
| Typ | Beschreibung | |-----|--------------| | String | Einfache Key-Value-Paare | | Hash | Objekte mit Feldern | | List | Geordnete Listen | | Set | Ungeordnete Mengen | | Sorted Set | Mengen mit Score | | Stream | Log-artige Datenstruktur |
Installation
Debian/Ubuntu
apt install redis-server
systemctl enable redis-server
systemctl start redis-serverDocker
version: '3'
services:
redis:
image: redis:7-alpine
container_name: redis
restart: unless-stopped
ports:
- "6379:6379"
volumes:
- redis_data:/data
command: redis-server --appendonly yes
volumes:
redis_data:Verbindung testen
redis-cli ping
# PONGGrundlegende Befehle
Strings
# Setzen
SET key "value"
SET user:1:name "Max"
# Mit Ablauf
SET session:abc123 "data" EX 3600
# Abrufen
GET key
# Löschen
DEL key
# Inkrementieren
INCR counter
INCRBY counter 10Hashes
# Hash setzen
HSET user:1 name "Max" email "max@example.de" age 30
# Einzelnes Feld
HGET user:1 name
# Alle Felder
HGETALL user:1
# Feld aktualisieren
HINCRBY user:1 age 1Listen
# Am Ende anfügen
RPUSH mylist "item1" "item2" "item3"
# Am Anfang anfügen
LPUSH mylist "item0"
# Abrufen
LRANGE mylist 0 -1 # Alle
LRANGE mylist 0 9 # Erste 10
# Entfernen
LPOP mylist
RPOP mylistSets
# Hinzufügen
SADD tags "redis" "database" "cache"
# Alle Mitglieder
SMEMBERS tags
# Prüfen
SISMEMBER tags "redis"
# Entfernen
SREM tags "cache"
# Operationen
SUNION set1 set2
SINTER set1 set2Sorted Sets
# Mit Score
ZADD leaderboard 100 "player1" 95 "player2" 88 "player3"
# Top N
ZREVRANGE leaderboard 0 9 WITHSCORES
# Rang abfragen
ZREVRANK leaderboard "player1"
# Score erhöhen
ZINCRBY leaderboard 5 "player2"Konfiguration
redis.conf
# /etc/redis/redis.conf
# Netzwerk
bind 127.0.0.1
port 6379
protected-mode yes
# Authentifizierung
requirepass "sicheres_passwort"
# Speicher
maxmemory 256mb
maxmemory-policy allkeys-lru
# Persistenz
appendonly yes
appendfsync everysec
save 900 1
save 300 10
save 60 10000
# Logging
loglevel notice
logfile /var/log/redis/redis-server.log
# Client-Limits
maxclients 10000
timeout 0Speicher-Policies
| Policy | Beschreibung | |--------|--------------| | noeviction | Fehler bei vollem Speicher | | allkeys-lru | LRU über alle Keys | | volatile-lru | LRU nur Keys mit TTL | | allkeys-random | Zufällig alle Keys | | volatile-random | Zufällig Keys mit TTL | | volatile-ttl | Keys mit kleinstem TTL |
Persistenz
RDB (Snapshots)
# redis.conf
save 900 1 # Nach 900s wenn 1 Änderung
save 300 10 # Nach 300s wenn 10 Änderungen
save 60 10000 # Nach 60s wenn 10000 Änderungen
dbfilename dump.rdb
dir /var/lib/redisAOF (Append Only File)
# redis.conf
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec # always, everysec, noManueller Save
redis-cli SAVE # Blockierend
redis-cli BGSAVE # BackgroundCaching-Pattern
Cache-Aside
import redis
r = redis.Redis(host='localhost', port=6379, decode_responses=True)
def get_user(user_id):
# Versuche aus Cache
cached = r.get(f'user:{user_id}')
if cached:
return json.loads(cached)
# Aus Datenbank laden
user = db.query(f'SELECT * FROM users WHERE id = {user_id}')
# In Cache speichern
r.setex(f'user:{user_id}', 3600, json.dumps(user))
return userWrite-Through
def update_user(user_id, data):
# Datenbank aktualisieren
db.update('users', user_id, data)
# Cache aktualisieren
r.setex(f'user:{user_id}', 3600, json.dumps(data))Cache-Invalidierung
def delete_user(user_id):
db.delete('users', user_id)
r.delete(f'user:{user_id}')Session-Storage
PHP
; php.ini
session.save_handler = redis
session.save_path = "tcp://127.0.0.1:6379?auth=password"Node.js (Express)
const session = require('express-session');
const RedisStore = require('connect-redis').default;
const redis = require('redis');
const redisClient = redis.createClient();
app.use(session({
store: new RedisStore({ client: redisClient }),
secret: 'keyboard cat',
resave: false,
saveUninitialized: false,
cookie: { secure: true, maxAge: 86400000 }
}));Pub/Sub
Publisher
redis-cli PUBLISH channel "Hello World"Subscriber
redis-cli SUBSCRIBE channelPython-Beispiel
# Publisher
r.publish('notifications', json.dumps({'type': 'alert', 'msg': 'Hello'}))
# Subscriber
pubsub = r.pubsub()
pubsub.subscribe('notifications')
for message in pubsub.listen():
if message['type'] == 'message':
print(message['data'])Cluster und Replikation
Master-Replica
# Auf Replica
redis-cli REPLICAOF master_host 6379
# Konfiguration
replicaof master_host 6379
masterauth master_passwordRedis Sentinel
# sentinel.conf
sentinel monitor mymaster 192.168.1.10 6379 2
sentinel auth-pass mymaster password
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000Monitoring
Info
redis-cli INFO
redis-cli INFO memory
redis-cli INFO replication
redis-cli INFO statsSlowlog
redis-cli SLOWLOG GET 10Monitoring
# Live-Befehle
redis-cli MONITOR
# Client-Liste
redis-cli CLIENT LISTPrometheus
# redis_exporter
docker run -d -p 9121:9121 \
oliver006/redis_exporter \
--redis.addr redis://localhost:6379Sicherheit
Authentifizierung
# Verbinden mit Passwort
redis-cli -a password
# In Anwendung
redis.Redis(host='localhost', port=6379, password='password')ACL (Redis 6+)
# Benutzer erstellen
ACL SETUSER myuser on >password ~cached:* +get +set +del
# ACL-Liste
ACL LISTNetzwerk
# Nur localhost
bind 127.0.0.1
# Mit Firewall
ufw allow from 192.168.1.0/24 to any port 6379Zusammenfassung
| Befehl | Funktion | |--------|----------| | SET/GET | String-Operationen | | HSET/HGET | Hash-Operationen | | LPUSH/RPUSH | Listen-Operationen | | SADD/SMEMBERS | Set-Operationen | | ZADD/ZRANGE | Sorted Set-Operationen | | EXPIRE/TTL | Ablaufzeit |
| Konfiguration | Empfehlung | |---------------|------------| | maxmemory | Je nach RAM | | maxmemory-policy | allkeys-lru für Cache | | appendonly | yes für Persistenz |
| Datei | Funktion | |-------|----------| | /etc/redis/redis.conf | Konfiguration | | /var/lib/redis/dump.rdb | RDB-Snapshot | | /var/lib/redis/appendonly.aof | AOF-Log |
Fazit
Redis ist unverzichtbar für performante Webanwendungen. Als Cache beschleunigt es Datenbankzugriffe erheblich. Die vielfältigen Datenstrukturen ermöglichen elegante Lösungen für komplexe Probleme. Pub/Sub eignet sich für Echtzeit-Kommunikation. Mit Sentinel oder Cluster lässt sich Hochverfügbarkeit erreichen. Die einfache API macht Redis zum Entwickler-Favoriten.