Die freie NoSQL-Datenbank Couch DB kann beides: offline arbeiten und sich in einem großen Verbund replizieren. Dieser Artikel stellt Anwendungsszenarien, Skalierungstechniken sowie eine Auswahl ergänzender Software für das Replikationswunder vor.
Über ein Vierteljahrhundert ist es her, dass Lotus Notes das Konzept eines verteilten Datenbanksystems realisiert hat. Seine Offline-Fähigkeit erfüllte eine wichtige Forderung der damaligen Zeit, denn digitale Zugänge in Firmennetze waren anfänglich unzuverlässige Modem- (später ISDN-)Dial-ups, die gelegentlich ausfielen. Datenbankgestützte Anwendungen gänzlich ohne bestehende Serververbindung laufen lassen – das war höchst innovativ.
Aktuelle Anforderungen
Die damaligen Gründe für ein verteiltes, replikationsfähiges Datenbanksystem sind heutzutage nicht mehr relevant. Dennoch schickt sich mit Couch DB [1] erneut ein Vertreter dieser Art von Datenbanken an, mit ganz ähnlichen Ansätzen und Konzepten den aktuellen Anforderungen zu begegnen. Dieser Artikel zeigt die heutigen Motivationen für ein derartiges Datenbanksystem und beschreibt die wichtigsten Anwendungsszenarien für Couch DB. Eine grundlegende Einführung in Couch DB findet sich in Oliver Frommels Online-Artikel [2].
Heute sollen Anwendungen in zwei Richtungen verlässlich skalieren: Beim Up-Scaling für das Web 2.0 müssen sie mit sehr hohen Lasten umgehen und beim Down-Scaling sollen sie für mobile Endgeräte taugen. Beim Einsatz unterwegs sollen Anwendungen zudem ohne permanente Netzanbindung funktionieren. So entwickelt etwa die Firma Couch One, in der Couch-DB-Erfinder Damien Katz CEO ist, eine hinsichtlich Arbeitsspeicher und Storage optimierte Android-Version von Couch DB [3]. Eine I-Phone-Version ist laut Jan Lehnardt vom selben Unternehmen fest in Planung.
Couch DB gibt auf diese unterschiedlichen Skalierungsanforderungen konzeptionelle Antworten, indem es als Kernfunktionalität Anwendung und Datenbestand repliziert und dabei nach dem Prinzip der Multiversion Concurrency Control (MVCC) arbeitet. Das bedeutet, dass Couch DB ohne Geschwindigkeitsverlust Daten lesen und schreiben kann, weil es sie ohne Transaktionslocks in fortlaufenden Revisionen abspeichert. Der Preis hierfür ist das notwendig größere Datenvolumen für die Revisionsstände der einzelnen Dokumente.
MVCC und die Konflikte
Das wesentliche Merkmal von Couch DB ist die Fähigkeit, die Dokumenten-basierten Datenbanken via Replikation beliebig verteilen zu können. Ein Replikationsvorgang ist unidirektional und kennt jeweils eine Quell- und eine Zieldatenbank, die auch beide auf demselben Couch-DB-Server residieren können.
Die Replikation zwischen zwei Datenbanken lässt sich auf der Kommandozeile mit Curl anstoßen. Der folgende Befehl veranlasst eine lokale Replikation von »db« nach »dbrep« :
curl http://127.0.0.1:5984/_replicate-H 'Content-Type: application/json'-d '{"source":"db", "target":"dbrep"}'
Abbildung 1 zeigt die alternative Bedienung über das mit Couch DB mitgelieferte Webfrontend Futon. Neben der Replikationsquelle »db« hat der Admin im Beispiel die Zieldatenbank »db-replica« definiert. Der Parameter »Continuous« für die Replikation bewirkt, dass Couch DB eine Quelle bei bestehender Netzverbindung kontinuierlich überwacht. Zusätzlich lässt sich eine Pollingzeit angeben (rote Markierungen).
Wer den Datenbestand bidirektional replizieren möchte, benötigt zwei Replikationsvorgänge. Couch DB ist hierbei in der Lage, einen inkonsistenten Datenbestand zu erkennen und mit Hilfe der Markierung »(“_conflicts”: true)« Konfliktrevisionen der Dokumente auszuweisen. Seit der Version 0.10 vergleicht Couch DB den MD5-Hash zweier Dokumente über die Eigenschaften Json-Body, Attachments und das »_deleted« -Flag, um zu entscheiden, ob es sich um einen Konflikt handelt. Das Speichern ohne inhaltliche Änderung und identische Änderungen führen seit dieser Version nicht mehr zu Konflikten.
Abbildung 2 zeigt das Auftreten eines Speicherkonflikts (gelber Bereich). Couch DB erzeugt bei der Replikation in solchen Situationen Konfliktrevisionen der Dokumente. Die Bestimmung, welches Dokument die Haupt- und Konfliktrevision wird, entscheidet Couch DB anhand von festen Regeln deterministisch (roter Bereich). Dies hat den Vorteil, dass für diese Feststellung keine Rückfragen nach weiteren Datenbankinformationen notwendig sind und somit keine Performanceprobleme im Betrieb auftreten. Anschließend müssen diese Konflikte redaktionell oder durch die Anwendung (semi-)automatisch gelöst werden (grüner Bereich).
Anwendungsdesign
Die Möglichkeit, dass in einer Couch-DB-Anwendung Replikationskonflikte entstehen, sollten Entwickler zwingend im Anwendungsdesign berücksichtigen. In den Lotus-Notes-Hochzeiten wurden nicht selten hochbezahlte IT-Consultants beauftragt diese zu lösen. Verschärfend wirkte der Umstand, dass häufig Workflow-Hintergrundprozesse diese mitverursachten, sodass keine automatisierte Konfliktlösung in Betracht kam.
Es gibt daher einige wichtige Designprinzipien, die Replikationskonflikte innerhalb einer Anwendung vermeiden helfen. Dazu gehört zunächst die Verteilung der Daten auf einzelne Dokumente. Beispielsweise sollte eine CRM-Anwendung die verschiedenen Daten innerhalb eines Kundenkontextes auf einzelne Dokumente aufspalten. Während das Hauptdokument nur die reinen Stammdaten des Kunden enthält, sind Kampagnendaten, Kommunikationsprotokolle und Ähnliches jeweils in eigenen Dokumenten abgebildet.
Schreibrechte
Ebenfalls empfehlenswert ist ein feingranulares Autorisierungsmodell der Schreibberechtigungen. Das oben genannte Hauptdokument sollten nur organisatorisch zuständige Mitarbeiter des Marketings ändern dürfen. Couch DB definiert die Schreibberechtigungen innerhalb einer Datenbank über die Auswertung der Validierungsfunktionen aller Designdokumente einer Datenbank. Sinnvoll ist auch eine Abstraktion über Rollen, wie dies exemplarisch der Javascript-Code in Listing 1 umsetzt.
Listing 1
Rollen
01 function(new_doc, old_doc, userCtx) {
02 if(userCtx.roles.indexOf("marketing") == -1) {
03 throw({unauthorized: "Sie haben nicht die Rolle 'marketing'."});
04 }
05 }
Sollen dennoch mehrere Parteien ein Dokument manipulieren dürfen, ist eine Request-basierte Anwendungsarchitektur eine gute Wahl (Abbildung 3). Diese folgt dem Grundsatz, dass prinzipiell alle Parteien ihren Änderungsauftrag in eine Request-Datenbank einstellen. Die Anwendungskonfiguration (»Config-DB« ) enthält die Information, auf welchem Datenbankserver die Requests abgearbeitet werden.

Abbildung 3: Bei mehreren schreibberechtigten Nutzern empfiehlt sich eine Request-basierte Anwendungsarchitektur.
Ein Szenario hierfür wäre die regelmäßige Dokumentenaktualisierung durch ein zentral gepflegtes Schlagwortregister bei synchroner redaktioneller Dokumentenpflege. Eine solche Architektur vermeidet nicht nur Konflikte, sondern erhöht auch die Anwendungssicherheit, indem beispielsweise externe Schnittstellen keinen direkten Schreibzugriff auf die eigentliche Anwendung erhalten.
Request-basiert
Abbildung 3 zeigt exemplarisch eine solche Anwendungsarchitektur. Ein Nutzer, der eine Änderung in der Replik der Applikation auf dem Berliner Server umsetzen möchte, erstellt dafür ein Request-Dokument in der Request-Datenbank. Die Anwendungskonfiguration (in der Config-DB) bestimmt, dass alle Änderungen der Daten ausschließlich auf dem Münchener Server umzusetzen sind. Das Request-Dokument repliziert auf den Münchener Server, wo der Request ausgeführt wird.
Da sich derzeit in Couch DB Leseberechtigungen nur datenbankweit vergeben lassen, ist es sinnvoll, derartige Konfigurationsinformationen in einer separierten Konfigurationsdatenbank abzulegen, die dann ebenso Teil der replizierenden Anwendungssuite wird.
Nicht direkt ein Designprinzip, aber dennoch dazu geeignet, die Wahrscheinlichkeit von Datenkonflikten zu verringern, sind Maßnahmen zur möglichst schnellen Verbreitung von Änderungen. Bewährt hat sich hierfür die Hub-Spoke-Topologie: Die Clients (Spokes, Speichen) replizieren jeweils mit einer Zentralinstanz (Hub, Nabe). Die Hubs gleichen ihren Datenbestand untereinander mit hoher Frequenz ab, sodass auch topologisch entfernte Clients Änderungen schnell erfahren.
Hintergrundprozesse
Couch DB galt anfänglich als nur für kleine bis mittlere Anwendungs-Setups geeignet. Ein typisches Szenario war das private Adressbuch, das zwischen Smartphone, Notebook und heimischem PC hin und her repliziert. Durch Umsetzung der oben genannten Designprinzipien lassen sich aber auch komplexere Anforderungen bedienen. Jedoch spätestens wenn Eskalationen, SLAs und Notifikationen Teil der Anforderungen werden, sind zeitgesteuerte Hintergrundprozesse notwendig. Bedauerlicherweise existiert in Couch DB bisher kein interner Scheduler, um Hintergrundprozesse anzustoßen. Natürlich lässt sich beispielsweise unter Linux der Cron-Daemon als Scheduler benutzen, die Nachteile eines solchen Designbruchs sind jedoch Plattformabhängigkeit, nicht konsistente Berechtigungen und die Unmöglichkeit, derartige anwendungsrelevante Konfigurationen in die Replikation einzubeziehen.
Weniger die Dezentralität von Anwendungen als vielmehr die massive Skalierung sind der Fokus einiger interessanter Projekte im Ökosystem rund um Couch-DB. Es existieren bereits verschiedene Lösungen und Ansätze, um horizontale Skalierung über mehrere Knoten zu verwirklichen.
Couch-DB-Lounge [5] ist ein Framework zur Partitionierung per HTTP-Reverse-Proxy und basiert auf dem Webserver/Proxy Nginx. Es umfasst ein Nginx-Modul sowie einen Python-Daemon und arbeitet als Consistent Hashing-Ring über alle Dokumente. Mit Hilfe der Datei »shards.conf« lässt sich die Datenpartitionierung (Sharding) definieren. Daten-Failover mit verschiedenen Nodes ist möglich.
Eine weitere Möglichkeit für die Partitionierung bietet Pillow [6]. Es stammt von dem Norweger Knut Hellan, der in dem überschaubaren Softwareprojekt insbesondere seine eigenen Anforderungen an die Fähigkeit zum automatischen Resharding umgesetzt hat.
Couch App
Wer einmal selbst eine Anwendung für Couch DB entwickeln möchte, dem sei als nützliches Entwicklungstool Couch App [4] empfohlen. Dabei handelt es sich um eine erweiterbare Sammlung von Python-Skripten, die eine Couch-DB-Applikation als Dateien in einer definierten Ordnerstruktur anlegt. In dieser Form lässt sich der Quelltext in ein verteiltes Versionskontrollsystem wie Git einchecken.
Das Deployment findet statt, indem der Entwickler die Dateien in eine Couch-DB-Instanz lädt. Couch App unterstützt damit den dezentralen Ansatz von Couch DB, indem es orthogonal zur replizierenden lauffähigen Couch-DB-Anwendung auch den Entwicklungsprozess verteilen kann.
Couch App setzt mindestens Python 2.5 voraus und lässt sich einfach installieren. Nach der Installation erzeugt der Befehl
couchapp generate Anwendung
eine neue Applikation. Die beiden Zeilen
cd Anwendung/ couchapp generate show Funktion
schreiben in das Verzeichnis »shows« die Datei »hello.js« , die der Entwickler nach dem Hinzufügen des Javascript-Programmcode mit
couchapp push http://localhost:5984/Anwendung
in die lokale Couch-DB-Instanz pusht.
Middleware oder Cluster
Einen generischen Ansatz verfolgt die Skalierungs-Middleware Gizzard [7]. Sie operiert zwischen einer Webanwendung, die Datenbankabfragen abschickt, und beliebigen Datenbanksystemen. Diese Vorgehensweise hat den Vorteil, dass sie im Gegensatz zum Consistent Hashing eine heterogene Partitionierung gestattet, sodass sich etwa häufig abgefragte Daten Performance-fördernd segmentieren lassen. Daneben kann man Forwarding-Strategien individuell festlegen.
Außerdem gestattet es Gizzard, Ressourcen dynamisch zum Cluster hinzuzufügen, was dem System Elastizität verleiht. Das System verhält sich sehr robust, da es beim Ausfall einer Partitionsreplik Requests dynamisch umleitet. Für den Fall, dass eine gesamte Partition nicht mehr erreichbar sein sollte, puffert Gizzard die ausstehenden Schreiboperationen in einem Transaktionsjournal.
Das jüngste und aktivste Upscaling-Projekt im Couch-DB-Umfeld ist jedoch Bigcouch [8], das sich stark an die konzeptionellen Ansätze aus dem Amazon Dynamo anlehnt. Dieser Couch-DB-Fork der Firma Cloudant arbeitet ebenfalls als elastischer Cluster und partitioniert die Daten auf Basis von Consistent-Hashing-Algorithmen. Daneben hält die Software View-Indizierung auf jeder Partition parallel vor, was zu deutlichen Performancegewinnen im Vergleich zu Standalone-Systemen führt. Neben der Gesamtanzahl von Knoten innerhalb eines Clusters steuern folgende vier Parameter Bigcouch dynamisch:
- Der Grad der Partitionierung als Anzahl »Q« der Shards eines Clusters.
- »N« , die Anzahl redundanter Kopien eines jeden Dokuments. (Die Empfehlung lautet »N > 2« .)
- Die Anzahl der Kopien, die gespeichert werden müssen, bevor ein Dokument “gespeichert” ist (»W« ). »W« ist damit die Stellschraube für die Konsistenz der Daten. »W=N« bedeutet vollständige Konsistenz, »W=1« führt zu maximalem Durchsatz.
- »R« , die verlangte Anzahl identischer Dokumentrepliken, bevor ein Lese-Request erfüllt ist. Während »R=1« eine minimale Latenz bedeutet, erzwingt »R=N« wiederum eine vollständige Konsistenz aller Dokumentkopien.
Standardmäßig erscheint Bigcouch auf Port 5984 dem Benutzer wie eine einzelne Couch-DB-Instanz. Daneben existiert aber auf Port 5986 die Möglichkeit, zu Administrationszwecken die einzelnen Nodes des Clusters direkt anzusprechen.
Couch DB stellt sich in drei verschiedenen Ausprägungen dar. Einerseits lädt es zum Downscaling auf Mobilgeräten ein, weil es geringe Ansprüche an die Hardware stellt. Zweitens erlaubt die Datenbank die horizontale Skalierung wie in früheren Lotus-Notes-Anwendungsszenarien. Die Web-2.0-Skalierung begegnet hoher Last und sehr großen Datenvolumina.
Der magische “Glue”, der diese unterschiedlichen Ausprägungen von Dezentralität möglich macht, besteht in der Fähigkeit von Couch DB, nicht nur Daten, sondern auch das Design von Anwendungen einfach und sehr robust zu replizieren.
Ausblick
Das Couch-DB-Universum zeigt sich dynamisch und innovativ. Mittel- bis langfristig gibt es aber noch einiges Potenzial auszuschöpfen. Die Möglichkeit, beispielsweise mit einem Form-Builder extrem einfach Couch-DB-Anwendungen für kleine und mittlere Unternehmen nutzbar zu machen, könnte einen bedeutenden Schub für Akzeptanz und Verbreitung der Software bewirken.
Kurzfristig ist für die kommende Version 1.1 mit einer verbesserten externen Programmierschnittstelle zu rechnen. Damit soll sich Couch DB auch als Reverse-Proxy konfigurieren lassen und externe Prozesse verwalten können. (mhu)
Infos
- Couch DB: http://couchdb.apache.org
- Oliver Frommel, “Mal ausspannen”: https://www.linux-magazin.de/Online-Artikel/CouchDB
- Android bei Couch One: http://www.couchone.com/page/android
- Couch App: http://www.couchapp.org
- Couch-DB-Lounge http://tilgovi.github.com/couchdb-lounge/
- Pillow: https://github.com/khellan/Pillow
- Gizzard: https://github.com/twitter/gizzard
- Bigcouch: https://github.com/cloudant/bigcouch









