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

Datenstrukturen

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

Docker

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

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

Hashes

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

Listen

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

Sets

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

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

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

AOF (Append Only File)

# redis.conf
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec  # always, everysec, no

Manueller Save

redis-cli SAVE      # Blockierend
redis-cli BGSAVE    # Background

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

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

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

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

Monitoring

Info

redis-cli INFO
redis-cli INFO memory
redis-cli INFO replication
redis-cli INFO stats

Slowlog

redis-cli SLOWLOG GET 10

Monitoring

# Live-Befehle
redis-cli MONITOR

# Client-Liste
redis-cli CLIENT LIST

Prometheus

# redis_exporter
docker run -d -p 9121:9121 \
    oliver006/redis_exporter \
    --redis.addr redis://localhost:6379

Sicherheit

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 LIST

Netzwerk

# Nur localhost
bind 127.0.0.1

# Mit Firewall
ufw allow from 192.168.1.0/24 to any port 6379

Zusammenfassung

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