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

OperationRedisMySQL
Lesen100.000+ ops/s1.000 ops/s
Schreiben80.000+ ops/s500 ops/s
Latenz<1 ms5-10 ms

Installation

Debian/Ubuntu

apt update
apt install redis-server

# Status prüfen
systemctl status redis-server

CentOS/RHEL

dnf install redis
systemctl enable --now redis

Version prüfen

redis-server --version
redis-cli --version

Grundlegende Befehle

Mit Redis verbinden

redis-cli

Strings (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 3

Schlü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 newkey

Listen

# 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 30

Sets (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 set2

Hashes (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 1

Sorted 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 yes

Speicher-Limits

PolicyBeschreibung
noevictionFehler wenn voll
allkeys-lruÄlteste Schlüssel löschen
volatile-lruNur Schlüssel mit TTL löschen
allkeys-randomZufällige Schlüssel löschen
volatile-ttlSchlü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/redis

AOF (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

BGSAVE

Sicherheit

Passwort setzen

# /etc/redis/redis.conf
requirepass IhrSuperGeheimesPasswort
# Verbinden mit Passwort
redis-cli -a IhrSuperGeheimesPasswort

# Oder im CLI
redis-cli
AUTH IhrSuperGeheimesPasswort

Gefä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.10

Redis 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:news

Python-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 replication

Wichtige 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 LIST

Echtzeit-Monitoring

redis-cli monitor

Langsame Queries

SLOWLOG GET 10

Backup und Restore

Backup

# RDB-Datei kopieren
cp /var/lib/redis/dump.rdb /backup/redis-$(date +%Y%m%d).rdb

Restore

# 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 redis

Replikation

Master-Slave

# Auf Slave-Server
# /etc/redis/redis.conf

replicaof master-ip 6379
masterauth master-passwort

Status prüfen

INFO replication

Redis 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

DatentypBefehle
StringSET, GET, INCR, EXPIRE
ListLPUSH, RPUSH, LPOP, LRANGE
SetSADD, SMEMBERS, SINTER
HashHSET, HGET, HGETALL
Sorted SetZADD, 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.