16. String
Key Value
player:1:name SuperPimp99 Klaus
player:1:score 12345
player:2:name MegaBasher12
player:2:score 45678
town:27:name Troja
… …
Wert schreiben
Schlüsselname Wert
SET player:1:name Klaus
OK
17. String
Key Value
player:1:name Klaus
player:1:score 12345
player:2:name MegaBasher12
player:2:score 45678
town:27:name Troja
… …
Wert schreiben, falls noch nicht vorhanden
Schlüsselname Wert
SETNX player:1:name Hans
0
18. String
Key Value
player:1:name Klaus
player:1:score 12345
player:2:name MegaBasher12
player:2:score 45678
town:27:name Troja
… …
Länge eines Strings bestimmen
Schlüsselname
STRLEN player:2:name
12
24. Liste
Key Value
… …
player:1:actions account:login build:main recruit:sword account:logout
… …
Sequenz von Elementen (Strings) in definierter Reihenfolge
max. 232-1 Elemente pro Liste
25. Liste
Key Value
… …
LPUSH RPUSH
player:1:actions account:login build:main recruit:sword account:logout account:login
… …
Elemente anhängen
Schlüsselname Wert
RPUSH player:1:actions account:login
5
26. Liste
Key Value
… …
player:1:actions build:main recruit:sword account:logout account:login
… LPOP … RPOP
account:login
Elemente entfernen
Schlüsselname
LPOP player:1:actions
"account:login"
27. Liste
Key Value
… …
player:1:actions build:main recruit:sword account:logout account:login
… …
Länge der Liste bestimmen
Schlüsselname
LLEN player:1:actions
4
28. Liste
Key Value
… …
player:1:actions build:main recruit:sword account:logout account:login
0 1 2 3
… … (-4) (-3) (-2) (-1)
Element an beliebiger Position auslesen
Schlüsselname Offset
LINDEX player:1:actions 1
"recruit:sword"
32. Hash
Key Value
… …
name SuperPimp99
player:1 level 12
experience 345
… …
assoziative Abbildung: String => String
max. 232-1 Schlüssel-Wert-Paare pro Hash
33. Hash
Befehle ähnlich wie bei Strings:
Attribut(e) schreiben/lesen (HSET, HGET, HMSET, HMGET)
alle Attribute lesen (HGETALL)
Attribut(e) löschen (HDEL)
Anzahl der Attribute bestimmen (HLEN)
Inkrementieren (HINCRBY)
Anwendungsbeispiele:
Objekt-Speicher / Objekt-Cache
34. Menge (Set)
Key Value
… …
active_users: 34 918
2012-08-17 7 713
291
… …
ungeordnete Sammlung von Elementen (Strings)
jedes Element höchstens einmal in Set vorhanden
max. 232-1 Elemente pro Set
48. Sortierte Menge (Sorted Set)
Anwendungsbeispiele:
Live-Ranking
sortierte Mitgliedschaften (Allianzmitglieder nach Beitrittsdatum
sortiert)
Index für Hash-Attribute
Hashes für Spieler-Objekte
"player:2": {"name": "Basher", "level": "50"}
Sorted Set als Index für "level"-Attribut
"player:levels": {score: 50, value: "2"}
Abfrage: IDs aller Spieler mit Level zwischen 50 und 100, absteigend
sortiert nach Level
SQL: SELECT id FROM players WHERE level BETWEEN 50 AND 100 ORDER
BY level DESC
Redis: ZREVRANGEBYSCORE player:levels 50 100
52. Lösung: Pipeline
Änderung der Abfolge von Senden u. Empfangen
S-E-S-E-S-E vs. S-S-S-E-E-E
Implementierung clientseitig
Befehlsausführung nicht atomar!
53. Beispiel: PHP + Predis
require 'predis/autoload.php';
$config = array( lokal entfernt (LAN)
'host' => 'localhost', ohne Pipeline 1,86 Sek. 5,13 Sek.
'port' => 6379,
'database' => 0, mit Pipeline 1,60 Sek. 1,48 Sek.
);
$redis = new PredisClient($config);
// ohne Pipeline
$start = microtime(true);
for ($i=0; $i<10000; $i++) {
$redis->set('key' . $i, $i);
}
printf("execution took %.2f secondsn", microtime(true) - $start);
// mit Pipeline
$start = microtime(true);
$redis->pipeline(function($pipe) {
for ($i=0; $i<10000; $i++) {
$pipe->set('key' . $i, $i);
}
});
printf("execution took %.2f secondsn", microtime(true) - $start);
54. Transaktionen
Abfolge: Beispiel:
Transaktion starten (MULTI) MULTI
Befehle senden OK
werden auf Server gesammelt SET first_key "test 1"
Antwort ist immer "QUEUED"
(Ausnahme: Syntaxfehler)
QUEUED
Transaktion ausführen (EXEC) SET second_key "test 2"
oder Transaktion abbrechen QUEUED
(DISCARD) SET third_key "test 3"
QUEUED
EXEC
OK
OK
OK
55. Transaktionen
Eigenschaften:
Ausführung atomar
"alles oder nichts"
bei DISCARD oder Verbindungsabbruch wird nichts ausgeführt
mit EXEC wird alles ausgeführt
Achtung: kein Abbruch/Rollback bei Fehlern!
56. Scripting
Unterstützung ab Redis 2.6
analog zu Stored Procedures
Sprache: LUA
Scriptausführung:
"on the fly":
LUA-Script 1. Parameter
EVAL "return redis.call('set', KEYS[1], 'bar')" 1 foo
OK Parameter-Anzahl
speichern und später ausführen:
LUA-Script
SCRIPT LOAD "return redis.call('set', KEYS[1], 'bar')"
"f8211e1772142e888d2b3eef9fd3894eb1b06b17"
SHA1-Hash des Scripts 1. Parameter
EVALSHA f8211e1772142e888d2b3eef9fd3894eb1b06b17 1 foo
OK Parameter-Anzahl
atomar => langsames Script kann Server ausbremsen!
64. Persistenz
RDB - Dump
"point-in-time snapshot"
wird erstellt, wenn X Update-Operationen in Y Sekunden erfolgt
Standardeinstellungen:
save 900 1 Dump, wenn mind. 1 Update in 15 Minuten
save 300 10 Dump, wenn mind. 10 Updates in 5 Minuten
save 60 10000 Dump, wenn mind. 10.000 Updates in 1 Minute
Vorteile:
Einspielen des Backups relativ schnell
Nachteile:
Datenverlust kann groß sein
Speichervorgang aufwendig (große Datenmenge)
65. Persistenz
AOF (append-only-file)
jeder einzelne Befehl geloggt
Wiedereinspielen der Daten durch Ausführung dieser Befehle
Schreib-Intervall konfigurierbar:
OS entscheidet (schnell)
jedes Query (langsam, aber sicher)
jede Sekunde (Kompromiss)
Vorteile:
relativ sicher, Datenverlust gering
Nachteile:
Einspielen des Backups langsam
66. Persistenz
RDB vs. AOF
keine Lösung besser oder schlechter als die andere
=> Entscheidung: Wie kritisch ist ein Datenverlust?
beides auch in Kombination nutzbar
67. Skalierbarkeit
Master-Slave-Replikation
1 Master, mehrere Slaves
Slaves können selbst weitere Slaves besitzen
Synchronisierung: Master -> Slave
Slaves können Schreiboperationen ausführen, aber nicht mit Master
synchronisieren!
einfache Handhabung:
Server als Slave starten: redis-server --slaveof 127.0.0.1 6379
automatische Synchronisierung
Auto-Reconnect bei Verbindungsabbruch
68. Skalierbarkeit
Redis Cluster (noch in Alpha-Phase!)
bis zu 4096 Knoten
Ziel: lineare Skalierbarkeit
Schlüssel werden auf Knoten verteilt ("Consistent Hashing")
Redundanz-Faktor konfigurierbar ("Live-Backup")
Jeder Schlüssel existiert auf 1 Master + N Slaves (Slaves = read-only)
Fehlertoleranz:
Knoten "pingen" sich gegenseitig
bei Timeout wird Knoten als "nicht verfügbar" markiert (alle Knoten des
Clusters werden informiert)
Wenn Knoten wieder online ist, wird er "runtergefahren" (mögliche
Dateninkonsistenz)