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

| 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/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

| 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.