Redis

Allgemein

Redis ist eine Open Source Key/Value-Datenbank, welche standardmäßig alle Daten im RAM speichert, womit sie zu den sogenannten Hauptspeicherdatenbanken? gehört. Die Daten aus dem Hauptspeicher werden nach einem konfigurierbaren Intervall auf der Festplatte gespeichert und sind dann persistent gespeichert. Somit ist Redis eine der schnellsten K/V-Datenbaken.

Steckbrief

Webadressehttp://code.google.com/p/redis/
KategorieKey/Value-Store mit Lists und Sets als zusätzlichen Values
APIRuby, Python, PHP, Erlang, Tcl, Perl, Lua, Java, Scala, Clojure, C+, C, JavaScript, C#, Scala und weitere
ProtokollÜber die Programmiersprache
Geschrieben inANSI C
Concurrencyin-memory und asynchron auf Platte oder Append Only
ReplikationMaster/Slave
SkalierungSharding mittels Consistent Hashing
LizenzNew-BSD-Lizenz

Tabelle: Redis-Steckbrief, entnommen aus Edlich (2010)

Die Keys werden als normale Zeichenketten in Redis gespeichert, als Values (auch Werte genannt) werden folgende Typen unterstützt:

  • Strings
  • Hashes
  • Listen mit möglichen Duplikaten
  • Sets ohne Duplikate
  • Sortierte Sets

Hashs funktionieren exakt wie Key/Values-Paare, unter einem Key wird ein Hash und ein Value gespeichert. Dies wird weiter unten genauer erläutert und anhand von Beispielen erklärt.

Wie oben erwähnt speichert Redis die Daten im Arbeitsspeicher und mit einem gewissen Intervall auf der Festplatte des Servers, dies nennt sich Snapshotting Mode. Der Intervall kann auf einen zeitlichen Wert oder eine Anzahl von Schreiboperationen gesetzt werden. Im Falle eines Crashs können die vergangenen Operationen nachgeladen werden, um den ursprünglichen Zustand wieder herzustellen. Neben dieser in-memory Variante gibt es die Möglichkeit Daten direkt auf der Festplatte zu speichern, den sogenannten Append Only File Mode. Redis findet vor allem Anwendung bei Caches, die beispielsweise Web- oder Sitzungsdaten (Sessions) speichern oder Daten für statistische Zwecke sammeln.

Installation

Die Installation von Redis gestaltet sich schnell und einfach. Die Datenbank läuft auf allen POSIX-kompatiblen Unix-Systemen problemlos, allerdings gibt es keine aktuelle Windows-Unterstützung. Für die Installation unter Ubuntu sollten folgende Befehle ausgeführt werden.

// Herunterladen des Archivs
$ wget http://redis.googlecode.com/files/redis-1.2.2.tar.gz

// Entpacken des Archivs in das Verzeichnis redis-1.2.2
$ tar xvzf redis-1.2.2.tar.gz

// Wechseln in das Verzeichnis redis-1.2.2
$ cd redis-1.2.2

// Kompilieren des Systems und erzeugen der Executable
$ make

// starten des Servers
$ ./redis-server

// Mit folgendem Befehl können die Kommandos global gemacht werden
$ sudo cp redis-server redis-cli /usr/local/bin

Wer Redis lediglich einmal testen möchte kann dies auch online unter http://try.redis-db.com tun.

Arbeiten mit Redis

Nachdem Redis installiert wurde, werden im Folgenden einige Befehle zum Arbeiten mit Redis beschrieben. Die Ausgabe des Systems wird rekursiv dargestellt und Veränderungen innerhalb der Datenbank sind als Kommentar markiert. Es ist wichtig zu erwähnen, dass die Keys von Redis case-sensitiv sind, d.h. ‚glas‘ ist ein anderer Schlüssel als ‚Glas‘. Als erstes kann mit dem Befehl INFO Informationen über die Datenbank ausgegeben werden.

INFO
redis_version:1.2.2
uptime_in_seconds:1324 ...

SET Glas 10001 // Speicher den Value '10001' mit dem Key 'Glas'
OK

SET Teller 10002 // Speicher den Value '10002' mit dem Key 'Teller'
OK

SET Gabel 10003 // Speicher den Value '10003' mit dem Key 'Gabel'
OK

KEYS '*' // Ausgabe aller Keys
Teller Glas Gabel

EXIST Teller // Prüft ob der Key 'Teller' vorhanden ist
1

DBSIZE // Gibt die Größe der Datenbank zurück
3

MOVE Glas 2 // Verschiebt den Key in die Datenbank Nummer 2
1

KEYS '*' // Ausgabe aller Keys
Teller Gabel

DEL Teller // Löscht den Key 'Teller'
1

FLUSHALL // Löscht alle Keys in allen Datenbanken (FLUSHDB für nur aktuelle DB)
OK

SET Tasse 10004 // Speicher den Value '10004' mit dem Key 'Tasse'
OK

EXPIRE Tasse 60 // Der Key 'Tasse' lebt jetzt noch 60 Sekunden
OK

SAVE // Speichert die im RAM befindlichen Daten auf der Festplatte
OK

LASTSAVE // gibt den Integer Zeitwert des letzten Speicherns zurück
1300143681

MSET Gabel 10003 Glas 10001 Teller 10002 // Multi-Set
OK

MGET Gabel Glas Teller // Multi-Get
1. 10003
2. 10001
3. 10002

SHUTDOWN // fährt den Server herunter
User requested shutdown, saving DB...
DB saved on disk
412587 bytes used at exit
Server exit now, bye bye...

Dies war ein Einstieg in den Umgang mit den normalen Key/Value Eintragungen. Die mit dem Befehl EXPIRE erzeugte TTL (Time To Live) bietet sich vor allem für Webanwendungen an, die flüchtige Informationen enthalten. So wird es ermöglich die Datenbank kompakt zu halten. Die M*-Befehle, wie beispielsweise MSET und MGET, ermöglichen es Bulk-Kommandos abzusetzen und somit Verbindungszeit zu sparen. Die Keys können mit beliebigen Sonderzeichen bestückt werden und schaffen somit neue Namensräume (Beispiel für einen Key mit Sonderzeichen Deutschland:Hessen:Frankfurt:Zeilgalerie).

Value Typen in Redis
Value Typen in Redis

Redis stellt neben Strings auch noch andere Value Typen zur Verfügung. In Abbildung "Value Typen in Redis" werden diese Typen grafisch abgebildet. Sets und Listen unterscheiden sich nur geringfügig. Innerhalb von Sets kann jedes Element nur einmal vorkommen, in Listen sind auch Duplikate möglich. Der wichtigste Unterschied ist, dass Listen meist als Stacks oder Queue verwenden werden, es kann also von oben sowie von unten zugegriffen werden. Bei Sets ist dies nicht möglich, die Elemente können nur von oben hinzugefügt oder gelöscht werden.

RPUSH Einkauf Melone // (Melone)
LPUSH Einkauf Banane // (Banane, Melone)
RPUSH Einkauf Apfel // (Banane, Melone, Apfel)
LRANGE Einkauf 0 -1 // Gibt die Liste auf 0 = erstes Element -1 = letztes Element
(Banane, Melone, Apfel)
RPUSH Einkauf Orange // (Banane, Melone, Apfel, Orange)
LPUSH Einkauf Orange // (Orange, Banane, Melone, Apfel, Orange)
LTRIM Einkauf 1 3 // Trimmt die Einkaufsliste auf (Banane, Melone, Apfel)
LINDES Einkauf 1 // Gibt das Element an Position 1 aus
(Melone)
LSET Einkauf 1 Wassermelone // Ersetzt das Element an der Index Position 1: (Banane, Wassermelone, Apfel)
RPUSH Einkauf Apfel // (Banane, Wassermelone, Apfel, Apfel)
LPUSH Einkauf Apfel // (Apfel, Banane, Wassermelone, Apfel, Apfel)
LREM Einkauf 2 Apfel // Löscht 2-mal Apfel von links beginnend: (Banane, Wassermelone, Apfel)
LPOP Einkauf // (Wassermelone, Apfel)
(Banane)
RPOP Einkauf // (Wassermelone)
(Apfel)

Das vorangegangene Code-Segment zeigt Beispielhaft das Arbeiten mit Listen. Im nächsten wird demonstriert, welche Befehle mit Sets möglich sind.

SADD Einkauf Melone // (Melone)
SADD Einkauf Melone // (Melone)
0 (false)
SADD Einkauf Apfel // (Apfel, Melone)
SMEMBERS Einkauf // Gibt alle Elemente aus
(Apfel, Melone)
SADD Einkauf Banane // (Banane, Apfel, Melone)
SRANDMEMBER Einkauf // gibt ein zufälliges Element aus
(Apfel)
SREM Einkauf Banane // (Apfel, Melone)
SPOP Einkauf // (Melone)
(Apfel)
SCARD Einkauf // Anzahl der vorhandenen Elemente
1
SISMEMBER Einkauf Apfel// Prüft ob Apfel in dem Set vorhanden ist
0 (false)

Zusätzlich gibt es noch die sortierten Sets die mit dem Befehl ZADD initialisiert werden können. Hierzu muss aber zusätzlich eine Gewichtung angegeben werden, nach der das Set sortiert werden soll, Beispiel: ZADD Gewicht 1.5 Apfel und ZADD Gewicht 2.5 Banane. Das sortierte Set „Gewicht“ erhält somit die Werte Apfel und Banane mit den Gewichtungen 1,5 und 2,5.

Bei dem Arbeiten mit Hashs werden unter einem Key ein Hash und ein Value gespeichert. Dies eignet sich ausgezeichnet um Objektfelder zu speichern.

HSET Mitarbeiter1 Nachname Meier // Erstellt den Eintrag Nachname
HSET Mitarbeiter1 Vorname Martin // Erstellt den Eintrag Vorname
HSET Mitarbeiter1 Gehalt 42000 // Erstellt den Eintrag Gehalt
HDEL Mitarbeiter1 Gehalt // Löscht den Eintrag Gehalt
HGET Mitarbeiter1 Nachname // Gibt den Wert des Nachnamens aus
(Meier)
HEXISTS Mitarbeiter1 Vorname // Prüft ob Vorname existiert
1
HLEN Mitarbeiter1 // Gibt die Anzahl der Keys aus
2
HKEYS Mitarbeiter1 // Gibt die alle Keys aus
(Nachname, Vorname) \\ HVALS Mitarbeiter1 // Gibt die alle Werte aus
(Meier, Martin)
HGETALL Mitarbeiter1 // Gibt alle Keys und Werte aus
((Nachname, Meier)(Vorname, Martin))

Natürlich bietet Redis auch die Möglichkeit anstatt über die Konsole Eingaben zu tätigen, dies auch über die JDBC-Bibliothek zu tun.

Replikation und Skalierung

Redis nutzt eine Master-N-Slaves-Replikation, wie sie exemplarisch in der Abbildung "Master-N-Slaves-Replikation" aufgezeigt ist.

Master-N-Slaves-Replikation
Master-N-Slaves-Replikation

Dies macht deutlich, dass es in Redis nur einen Master gibt, der an beliebig viele Slaves in Reihe und/oder Serie geschaltet werden kann. Die Slaves synchronisieren sich mit dem Master, indem sie ihm ein SYNC-Kommando schicken. Der Master kann so konfiguriert werden, dass er nicht auf die Festplatte speichert, sondern das der Slave persistent schreibt. Ebenfalls ist es möglich alle komplexen Abfragen an die Slaves weiter zugeben, was ebenfalls zur Optimierung der Antwortzeit des Masters beiträgt.

Da Redis nicht nativ skaliert, ist das eigenständige Verteilen und Einfügen von neuen Knoten, auf welche die Daten verteilt werden, zurzeit noch nicht möglich. Erst ab Version 2.0 bietet die Datenbank eine standardisierte Skalierung an. Dennoch gibt es andere Möglichkeiten die Performance zu steigern. Zum einem können durch Client-Sharing die Client-Daten auf mehrere Redis-Nodes verteilt werden. Dies ist am einfachsten auf der Applikationsebene zu realisieren. Im Pipelining können mehrere Kommandos in einem Client-Request versendet werden, um somit Verbindungszeit zu sparen. Ebenfalls ist der Einsatz von Multiprozessoren auf einem Server sinnvoll. Ein Quad-Core-System kann durchaus vier Redis-Server verwalten, diese müssen aber über unterschiedliche Ports angesprochen werden.

Vorteile

Zwar tut sich Redis schwer mit komplexen Abfragen, ist aber dennoch eines der schnellsten Key/Value-Systeme. So kann Redis auf einer durchschnittlichen LINUX-Maschine 100.000 Lese- oder Schreib-Operationen von Key/Value-Paaren binnen einer Sekunde durchführen. Wie weiter oben beschrieben wurde, geht auch die Implementierung von Redis schnell von statten. Ein weiterer Vorteil ist, dass die API von Redis einfach und klar aufgebaut ist, was das Schreiben von eigenen Client-Bibliotheken erleichtert.

Nachteile

Natürlich hat Redis auch einige Schwächen. So ist bei der in-memory Variante immer darauf zu achten, dass die Daten alle in dem RAM passen müssen, was nicht immer der Fall ist. Zusätzlich kann Redis noch nicht selbst skalieren, was im Petabyte-Bereich zu Problemen führen kann. Bei einigen Anwendungsbereichen kann es von Nachteil sein, dass Redis typenlos ist, da es alles als String/Bytearray speichert. Jedoch bieten einige APIs Möglichkeiten, dies zu umgehen. So ist es möglich JSON/BSON-Dateien als Values mit Typinformationen zu speichern, was aber einen geringen Performanceverlust bei der Serialisierung zur Folge hat.

Quellen:

Kategorie: Neue DB-Entwicklungen, NoSQL, KeyValue-DB, R