Redis ist eine schnelle In-Memory-Datenbank, die als Cache, Message-Broker und Session-Store eingesetzt wird. Sie kann Millionen Operationen pro Sekunde verarbeiten.
Warum Redis?
Anwendungsfälle
- Caching (Datenbank-Queries, API-Responses)
- Session-Speicher (PHP, Node.js)
- Warteschlangen (Job-Queues)
- Pub/Sub (Real-time Messaging)
- Zähler und Statistiken
- Rate-Limiting
- Leaderboards (Sorted Sets)Performance
| Operation | Redis | MySQL | |-----------|-------|-------| | Lesen | 100.000+ ops/s | 1.000 ops/s | | Schreiben | 80.000+ ops/s | 500 ops/s | | Latenz | <1 ms | 5-10 ms |
Installation
Debian/Ubuntu
apt update
apt install redis-server
# Status prüfen
systemctl status redis-serverCentOS/RHEL
dnf install redis
systemctl enable --now redisVersion prüfen
redis-server --version
redis-cli --versionGrundlegende Befehle
Mit Redis verbinden
redis-cliStrings (einfache Werte)
# Wert setzen
SET name "Max"
# Wert lesen
GET name
# Mit Ablaufzeit (Sekunden)
SET session:123 "user_data" EX 3600
# Ablaufzeit in Millisekunden
SET cache:key "value" PX 60000
# Nur setzen wenn nicht existiert
SETNX lock:resource "1"
# Mehrere Werte
MSET key1 "value1" key2 "value2"
MGET key1 key2
# Inkrementieren
SET counter 0
INCR counter
INCRBY counter 5
# Dekrementieren
DECR counter
DECRBY counter 3Schlüssel verwalten
# Schlüssel auflisten
KEYS *
KEYS user:*
# Schlüssel existiert?
EXISTS name
# Schlüssel löschen
DEL name
# Ablaufzeit setzen
EXPIRE name 60
# Ablaufzeit prüfen
TTL name
# Typ prüfen
TYPE name
# Umbenennen
RENAME oldkey newkeyListen
# Am Ende hinzufügen
RPUSH mylist "item1" "item2" "item3"
# Am Anfang hinzufügen
LPUSH mylist "item0"
# Elemente abrufen
LRANGE mylist 0 -1
# Länge
LLEN mylist
# Element entfernen und zurückgeben
LPOP mylist
RPOP mylist
# Blockierendes Pop (für Queues)
BLPOP mylist 30Sets (eindeutige Werte)
# Hinzufügen
SADD tags "redis" "database" "cache"
# Alle Mitglieder
SMEMBERS tags
# Ist Mitglied?
SISMEMBER tags "redis"
# Anzahl
SCARD tags
# Entfernen
SREM tags "cache"
# Zufälliges Element
SRANDMEMBER tags
# Operationen
SUNION set1 set2
SINTER set1 set2
SDIFF set1 set2Hashes (Objekte)
# Felder setzen
HSET user:1 name "Max" email "max@example.com" age 30
# Einzelnes Feld lesen
HGET user:1 name
# Alle Felder lesen
HGETALL user:1
# Feld existiert?
HEXISTS user:1 name
# Feld löschen
HDEL user:1 age
# Alle Schlüssel
HKEYS user:1
# Alle Werte
HVALS user:1
# Inkrementieren
HINCRBY user:1 visits 1Sorted Sets (mit Score)
# Hinzufügen mit Score
ZADD leaderboard 100 "player1" 85 "player2" 120 "player3"
# Aufsteigend sortiert
ZRANGE leaderboard 0 -1
# Mit Scores
ZRANGE leaderboard 0 -1 WITHSCORES
# Absteigend (Top 10)
ZREVRANGE leaderboard 0 9 WITHSCORES
# Rang eines Mitglieds
ZRANK leaderboard "player1"
ZREVRANK leaderboard "player1"
# Score abfragen
ZSCORE leaderboard "player1"
# Score erhöhen
ZINCRBY leaderboard 10 "player1"Konfiguration
redis.conf
# /etc/redis/redis.conf
# Netzwerk
bind 127.0.0.1
port 6379
# Passwort
requirepass IhrSicheresPasswort
# Speicher
maxmemory 256mb
maxmemory-policy allkeys-lru
# Persistenz
save 900 1
save 300 10
save 60 10000
# Logging
loglevel notice
logfile /var/log/redis/redis-server.log
# Sicherheit
protected-mode yesSpeicher-Limits
| Policy | Beschreibung | |--------|--------------| | noeviction | Fehler wenn voll | | allkeys-lru | Älteste Schlüssel löschen | | volatile-lru | Nur Schlüssel mit TTL löschen | | allkeys-random | Zufällige Schlüssel löschen | | volatile-ttl | Schlüssel mit kürzester TTL zuerst |
Persistenz
RDB (Snapshots)
# /etc/redis/redis.conf
# Speichern wenn: nach X Sekunden Y Änderungen
save 900 1 # 1 Änderung in 15 Minuten
save 300 10 # 10 Änderungen in 5 Minuten
save 60 10000 # 10000 Änderungen in 1 Minute
dbfilename dump.rdb
dir /var/lib/redisAOF (Append-Only File)
# /etc/redis/redis.conf
appendonly yes
appendfilename "appendonly.aof"
# Sync-Optionen
# appendfsync always # Jede Operation (langsam, sicher)
appendfsync everysec # Jede Sekunde (Kompromiss)
# appendfsync no # OS entscheidet (schnell, riskant)Manueller Snapshot
BGSAVESicherheit
Passwort setzen
# /etc/redis/redis.conf
requirepass IhrSuperGeheimesPasswort# Verbinden mit Passwort
redis-cli -a IhrSuperGeheimesPasswort
# Oder im CLI
redis-cli
AUTH IhrSuperGeheimesPasswortGefährliche Befehle umbenennen
# /etc/redis/redis.conf
rename-command FLUSHALL ""
rename-command FLUSHDB ""
rename-command CONFIG ""
rename-command DEBUG ""Netzwerk einschränken
# Nur lokal
bind 127.0.0.1
# Bestimmte IPs
bind 127.0.0.1 192.168.1.10Redis als Session-Store
PHP
// php.ini
session.save_handler = redis
session.save_path = "tcp://127.0.0.1:6379?auth=passwort"Node.js (Express)
const session = require('express-session');
const RedisStore = require('connect-redis').default;
const { createClient } = require('redis');
const redisClient = createClient({
url: 'redis://localhost:6379',
password: 'passwort'
});
redisClient.connect();
app.use(session({
store: new RedisStore({ client: redisClient }),
secret: 'session-secret',
resave: false,
saveUninitialized: false,
cookie: { maxAge: 86400000 }
}));Redis als Cache
Caching-Muster
import redis
import json
r = redis.Redis(host='localhost', port=6379, password='passwort')
def get_user(user_id):
# Aus Cache versuchen
cached = r.get(f'user:{user_id}')
if cached:
return json.loads(cached)
# Aus Datenbank laden
user = database.get_user(user_id)
# In Cache speichern (1 Stunde)
r.setex(f'user:{user_id}', 3600, json.dumps(user))
return user
def invalidate_user(user_id):
r.delete(f'user:{user_id}')PHP-Beispiel
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->auth('passwort');
function getCachedData($key, $ttl, $callback) {
global $redis;
$cached = $redis->get($key);
if ($cached !== false) {
return json_decode($cached, true);
}
$data = $callback();
$redis->setex($key, $ttl, json_encode($data));
return $data;
}
// Verwendung
$users = getCachedData('all_users', 600, function() {
return $db->query("SELECT * FROM users")->fetchAll();
});Pub/Sub
Publisher
PUBLISH channel:news "Neue Nachricht!"Subscriber
SUBSCRIBE channel:newsPython-Beispiel
import redis
r = redis.Redis(host='localhost', port=6379)
# Publisher
r.publish('notifications', 'Neue Benachrichtigung')
# Subscriber
pubsub = r.pubsub()
pubsub.subscribe('notifications')
for message in pubsub.listen():
if message['type'] == 'message':
print(f"Received: {message['data']}")Monitoring
INFO-Befehl
INFO
INFO memory
INFO stats
INFO replicationWichtige Metriken
# Speicher
INFO memory
# used_memory_human
# maxmemory_human
# Statistiken
INFO stats
# total_connections_received
# total_commands_processed
# keyspace_hits
# keyspace_misses
# Aktive Clients
CLIENT LISTEchtzeit-Monitoring
redis-cli monitorLangsame Queries
SLOWLOG GET 10Backup und Restore
Backup
# RDB-Datei kopieren
cp /var/lib/redis/dump.rdb /backup/redis-$(date +%Y%m%d).rdbRestore
# Redis stoppen
systemctl stop redis
# Dump kopieren
cp /backup/redis-20260126.rdb /var/lib/redis/dump.rdb
chown redis:redis /var/lib/redis/dump.rdb
# Redis starten
systemctl start redisReplikation
Master-Slave
# Auf Slave-Server
# /etc/redis/redis.conf
replicaof master-ip 6379
masterauth master-passwortStatus prüfen
INFO replicationRedis mit Docker
# docker-compose.yml
version: '3.8'
services:
redis:
image: redis:7-alpine
command: redis-server --requirepass mypassword
ports:
- "6379:6379"
volumes:
- redis-data:/data
volumes:
redis-data:Zusammenfassung
| Datentyp | Befehle | |----------|---------| | String | SET, GET, INCR, EXPIRE | | List | LPUSH, RPUSH, LPOP, LRANGE | | Set | SADD, SMEMBERS, SINTER | | Hash | HSET, HGET, HGETALL | | Sorted Set | ZADD, ZRANGE, ZRANK |
Fazit
Redis ist unverzichtbar für schnelle Webanwendungen. Als Cache reduziert es Datenbankabfragen, als Session-Store skaliert es PHP-Anwendungen, und als Pub/Sub-Broker ermöglicht es Echtzeit-Kommunikation. Achten Sie auf Speicher-Limits, konfigurieren Sie Persistenz nach Bedarf und schützen Sie Redis immer mit einem Passwort.