1 Überblick über NoSQL Datenbanken Seminararbeit Software Systems Engineering - WS 2012 / 2013 Mario David - Student - Master Informatik (SSE) Universität zu Lübeck Zusammenfassung—Diese Seminararbeit umfasst die Einführung, die theoretischen Grundlagen, eine Taxonomie sowie einige exemplarische Beispiele aus dem Bereich von NoSQL Datenbanken. Nach einer Einführung der Begriffe sowie einer Motivation von dem relationalen Modell abzurücken wird u.a. auf das CAP-Theorem als theoretische Grundlage eingegangen. Desweiteren werden verschiedene NoSQL Datenbanken kategorisiert und diese Kategorien einzeln beschrieben. Dabei werden die beiden Datenbankmanagementsysteme Riak und CouchDB in ihren Grundzügen vorgestellt und deren jeweilige Vorzüge herausgearbeitet. Abschließend wird eine Zusammenfassung gegeben, die beschreibt wo die KernUnterscheide zu RDBM-Systemen bestehen. Index Terms—NoSQL, Taxonomy, Key-Value-Stores, CAPTheorem, document oriented databases, Riak, CouchDB I. E INF ÜHRUNG IN N O SQL Der Begriff NoSQL (not only SQL) beschreibt, statt einer konkreten Technologie, verschiedenste Ansätze im Bereich Persistenz. Diese Technologien besitzen als kleinsten gemeinsamen Nenner die Eigenschaft, nicht auf dem relationalen Datenbankmodell aufzubauen. Das relationale Datenbankmodell beruht im Wesentlichen auf Entitäten, dies entspricht einer Tabelle mit Spalten und Zeilen, und Relationen, also Beziehungen zwischen diesen Entitäten. Zusätzlich besitzen bieten relationale Datenbanksysteme unter dem Akronym ACID eine starke Konsistenz für Transaktionen. Diese Eigenschaft lässt sich nur schlecht mit einer Anforderung nach horizontaler Skalierung vereinbahren, da um Konsistenz über mehrere Knoten zu gewährleisten ein großer Kommunikationsaufwand betrieben werden muss. Es gibt allerdings noch weitere Faktoren, die eine Motivation sein können, von dem relationalen Modell Abstand zu nehmen: • • • • B. Einsatz von NoSQL Datenbanken NoSQL Datenbanken konzentrieren sich in den meisten Fällen auf einen Teilaspekt, wie bspw. Skalierbarkeit oder auch ein ausgeprägtes Datenmodell. Durch diese Spezialisierung bzw. diesen Kompromiss ist der Einsatz einer NoSQL Datenbank immer nur in Teilbereichen eines Gesamtsystems zu evaluieren. Auch relationale Datenbanken haben Vorteile, wie z.B. die Transaktionsfähigkeit oder den hohen Standardisierungsgrad der Abfragesprache (SQL). Daher ist der Einsatz von NoSQL Technologien häufig auch als Zu- und nicht Ersatz für bereits bestehende Datenbanksysteme zu sehen. C. Kategorien im nicht relationalen Umfeld Wie bereits angesprochen gibt es viele verschiedene Arten von Datenbanken, die alle unter dem Schlagwort NoSQL zusammengefasst werden. Diese lassen sich in verschiedene Kategorien unterteilen: • • • A. Motivation für nicht relationale Datenbanksysteme Diese sogenannte horizontale Skalierung (“Scale Out” Skalierung über mehrere Computer) ist häufig Voraussetzung für Applikationen, die das Nutzeraufkommen mittelfristig schlecht abschätzen können (Facebook, Google, Twitter, usw.). Man spricht in diesem Zusammenhang auch von “InternetScale Systems”. Traditionelle relationale Datenbanken skalieren üblicherweise vertikal (“Scale-Up”), sprich: ein Computer wird mit entsprechend größerer Hardware ausgestattet, um steigenden Anforderungen weiterhin zu genügen. Diese Art der Skalierung funktioniert gut für Applikationen, bei denen das Nutzeraufkommen ein gewisses Maß an Elastizität nicht übersteigt. Existieren allerdings Skalierungsanforderungen wie die oben genannten, so lässt sich diese Art der Datenbankskalierung sowohl aus technischen, als auch als Kostengründen nicht durchführen. kein Zwang für ein fest definiertes Schema der Datenbank Hochverfügbarkeit Kostenvorteile bei Scale Out gegenüber Scale Up neuartige Abfragemethoden (bspw. Map Reduce) • Key-Value Stores Spaltenorientierte Datenbanken Dokumentenorientierte Datenbanken Graphendatenbanken Die meisten Datenbanken, die dem Begriff NoSQL zugeordnet werden, lassen sich einer dieser Kategorien zuordnen. In den nachfolgenden Kapiteln wird auf die einzelnen Kategorien detailliert eingegangen und ggf. eine Datenbank aus dieser Kategorie näher betrachtet. Zuvor wird jedoch auf verschiedene theoretische Grundlagen eingegangen, die alle der NoSQL Datenbanken gemeinsam betreffen. II. T HEORETISCHE G RUNDLAGEN In diesem Kapitel werden verschiedene theoretische Grundlagen besprochen, die viele der Vorteile einer NoSQL Datenbank überhaupt erst ermöglichen. Desweiteren wird noch auf das sogenannte CAP-Theorem eingegangen, welches eine theoretische Basis für alle verteilten Systeme darstellt. 2 A. Horizontale Skalierung durch Sharding und Replikation Die Möglichkeit horizontal über mehrere Knoten zu skalieren verdanken viele NoSQL Datenbanken dem sogenannten Sharding. Bei dieser Technologie werden die zu persistierenden Daten horizontal über verschiedene Knoten partitioniert. Ein Beispiel für eine solche (auch wenn nicht gerade sinnvolle) Partitionierung ist, die gespeicherten Kundeninformationen anhand des ersten Buchstabens des Namens auf 26 ClusterKnoten einer NoSQL Datenbank zu verteilen. Ein wichtiger Aspekt ist hierbei, dass die einzelnen Knoten im Cluster Anfragen lokal beantworten können müssen. Ansonsten würden Join-Operationen über verschiedene Knoten stattfinden, wodurch die angestrebte Skalierbarkeit negativ beeinflusst wird. Diese lokale Anfragenbearbeitung wird häufig über Replikation und de-normalisierte Daten gelöst. Statt auf einen genauen Schnitt der Daten, bei dem exakt jeder Datensatz einem Knoten zugeordnet ist, zu setzen, werden die Daten dazu auf mehreren Knoten vorgehalten, um lokale Verarbeitung zu ermöglichen. De-normalisierte Daten ermöglichen diese lokale Verarbeitung dadurch, dass bspw. bei einer dokumentenorientierten Datenbank zu einem Kunden zusätzlich alle Bestellungen dieses Kunden als Attribut gespeichert werden, obwohl die Bestelldaten zusätzlich unter einem anderen Key / Knoten zu finden sind. Die Replikation spielt an dieser Stelle eine entscheidende Rolle. Viele NoSQL Datenbanken verlassen sich, statt auf einer geringen Anzahl von hochverfügbaren Servern, auf eine Vielzahl von Servern, die isoliert betrachtet nicht hochverfügbar sind. Ein Ausfall eines Knoten im Cluster kann toleriert werden, da die Daten immer auf mehreren Knoten zur Verfügung stehen. Dass dieser Fall, der Ausfall eines Knoten, im NoSQL Bereich als normal angesehen wird zeigt auch die Verwendung einer verteilten Hashtabelle. Auf diese spezielle Art einer Hashtabelle wird nachfolgend eingegangen. B. Verteilte Hashtabellen Einer der Vorreiter im Bereich NoSQL Datenbanken ist Amazon Dynamo[1]. Die im Jahr 2007 vorgestellte Lösung verwendet intern zur Kommunikation zwischen den Knoten des Clusters verteilte Hashtabellen (Distributed Hash Tables, DHT’s). Diese ermöglichen innerhalb eines P2PNetzwerkes die Ressourcenlokalisierung effizient und schnell durchzuführen. Verteilte Hashtabellen basieren auf dem Prinzip des sog. “consistent hashing”. Diese besondere Form des Hashings optimiert den Beitritt, Ausfall und Austritt eines Knoten im Netzwerk, da hier nicht der gesamte Datenbestand neu umverteilt werden muss, sondern lediglich die betroffenen Keys auf die Umliegenden Knoten verteilt werden. C. CAP Theorem Alle Arten von verteilten Systemen unterliegen dem CAPTheorem. Es wurde von Eric A. Brewer[2] aufgestellt und beschreibt die Eigenschaft, dass ein verteiltes System nur 2 von 3 der folgenden Eigenschaften vollständig erfüllen kann: • Konsistenz (C) • Verfügbarkeit (A) Partitionstoleranz (P ) Konsistenz ist die Eigenschaft, dass alle Knoten zu gleichen Zeit die gleichen Daten sehen. Verfügbarkeit beschreibt die Eigenschaft in der jede Anfrage von dem System beantwortet werden kann und Partitionstoleranz bedeutet, dass das Gesamtsystem auch bei Verlust von Nachrichten oder Netzwerkpartitionierung in der Lage ist weiterzuarbeiten. Bei dem Eintreten einer Netzwerkpartitionierung, bspw. durch die Verbindungsunterbrechung zwischen zwei Rechenzentren entsteht eine Situation, in der die Daten der Replikate nicht mehr überall konsistent sind. Die Entscheidung, wie auf diese Situation reagiert wird, obliegt meist1 dem Entwickler der NoSQL Datenbank. Entweder die zurückgelieferten Daten sind konsistent (C&P), wodurch evtl. manche Anfragen nicht mehr beantwortet werden können, oder alle Anfragen werden beantwortet, sind jedoch ggf. nicht konsistent (A&P). Die ursprüngliche Formulierung von Eric Brewer in seiner Präsentation im Jahre 2000[3] lautete: A shared-data system can have at most two of the three following properties: Consistency, Availability, and tolerance to network Partitions. Dies ist in der Realität, wie Brewer 2012 selbst klarstellte[4] nicht anzutreffen, da wie oben beschrieben die Situation einer Netzwerkpartitionierung in WAN Umgebungen jederzeit entstehen kann und somit die Entwickler von NoSQL Lösungen im wesentlichen lediglich die Wahl zwischen C und A haben (ggf. wird dem Benutzer der Datenbank die Entscheidung überlassen - siehe Riak: III-A4). Eine häufig gewählte Antwort bzw. ein für viele Anwendungsfälle akzeptabler Kompromiss auf die angesprochene Entscheidung ist BASE. Dieses Akronym steht für die englischen Begriffe “basically available, soft state, eventually consistent”. Es beschreibt die Eigenschaft, dass ein verteiltes System grundsätzlich verfügbar ist, allerdings nicht jeder Knoten des Clusters zwangläufig die gleichen Daten zu gleichen Zeit sieht (dies schlussendlich jedoch tut). Der Begriff “eventually consistency“ wurde vornehmlich durch Werner Vogels (CTO von Amazon) in seinem gleichnamigen Artikel[5] geprägt. BASE erfüllt die Eigenschaften A&P des CAP-Theorems und wird häufig von Datenbanken eingesetzt, die auf Ausfallsicherheit spezialisiert sind. Ein Beispiel für eventually consistent ist der weltweite Domain Name Service (DNS). Bei der Registrierung einer neuen Domain dauert die komplette Propagierung der Informationen zu allen DNS Servern eine gewisse Zeit. Innerhalb dieser Zeit sind die DNS Server an sich jedoch verfügbar (sofern sie erreichbar sind), auch wenn sie ggf. noch nicht die korrekten Daten liefern. • III. K EY-VALUE S TORES Diese Art von Datenbanken speichert, wie der Name schon vermuten lässt, immer zu einem gegebenen Schlüssel (Key) einen beliebigen Wert (Value) ab. Diese einfache Art der Datenspeicherung ist in der Regel sehr performant und lässt sich gut skalieren. Allerdings ist eine solche Datenbank häufig nicht gut geeignet, um komplexe Abfragen zu realisieren, da die 1 Ggf. ist es möglich als Anwender zur Laufzeit diese Entscheidung zu treffen. Siehe III-A4 3 Datenbank meist nichts über die Struktur der Werte weiß. Man kann innerhalb dieser Kategorie noch zwischen In-Memory Datenbanken und persistenten Datenbanken unterscheiden. Ein Beispiel für eine In-Memory Datenbank, die ihren gesamten Datenbestand im Hauptspeicher hält ist memcached[6]. Für eine persistente Variante ist hier bspw. Riak[7] zu nennen, auf die nachfolgend detailliert eingegangen wird. Weitere Datenbanken in dieser Kategorie sind Apache Cassandra[8], Amazon Dynamo[9] und Redis[10]. A. RESTful Dynamo Implementierung: Riak Riak ist ein verteilter Key-Value Store, der auf den Prinzipien der Amazon Dynamo Veröffentlichung basiert. Implementiert ist Riak in Erlang, einer funktionalen Programmiersprache für die Entwicklung von verteilten Systemen. Die Philosophie hinter Erlang: “Let it crash”, erkennt man auch in Riak wieder. Riak ist fehlertolerant. Das bedeutet, dass es ein völlig normaler Vorgang ist, Knoten zum Datenbank-Cluster hinzuzufügen und zu entfernen (beabsichtigt oder unbeabsichtigt). 1) Zugriffsmöglichkeiten: Wie viele NoSQL Datenbanken, ist auch für Riak die primäre Zugriffsmöglichkeit das HTTP Protokoll mit der angebotenen REST Schnittstelle. Anfragen an die Datenbank werden via URLs gestellt. Über Headerinformationen und HTTP-Verben lassen sich unterschiedliche Arten von Anfragen realisieren. Riak antwortet mit den gängigen HTTP-Statuscodes zur Beschreibung des Status der Anfrage. Durch die Verwendung von HTTP als Zugriffsprotokoll bietet Riak für jeder Programmiersprache eine Verbindungsmöglichkeit, die in der Lage ist HTTP-Anfragen zu generieren (bzw. Bibliotheken dafür bereitstellt). Somit ist es nicht notwendig einen Datenbanktreiber für jede Programmiersprache zu erstellen. Ebenfalls bietet HTTP Möglichkeiten wie Caching, Security und MIME Types, von denen Riak profitieren kann, ohne dass es eigene Mechanismen dafür bereitstellen muss. HTTP als Transportprotokoll hat allerdings auch einige Nachteile. So ist die Tatsache, dass HTTP ein ASCII-Protokoll ist, ein Nachteil bezüglich der Übertragungsgeschwindigkeit. Für diesen speziellen Fall ist es auch möglich Riak über das Binärprotokoll “Google Protocol Buffers”[11] anzusprechen. 2) CRUD: Für die Kommunikation mit dem Riak Server wird in diesen Beispielen das Kommandozeilen-Werkzeug cURL[12] verwendet. In Riak entspricht eine Datenbank in etwa einem sogenannten Bucket. Ein Bucket ist eine virtueller Schlüsselraum, in dem jeder Schlüssel eindeutig sein muss. Zudem ist es möglich für jeden Bucket verschiedene, voneinbobander isolierte Konfigurationen einzustellen[13]. Das Standard URL Schema lautet folgendermaßen: http://localhost:10018/riak/[bucket_name]/[key] Für die Erzeugung eines Datensatzes gibt es zwei Möglichkeiten. Entweder durch explizite Angabe des Keys unter dem der Datensatz später zu finden sein soll: Anbei ein Beispiel für die erste Variante: $ curl -v -X PUT http://localhost:10018/riak/dogs/ bob -H ’Content-type: application/json’ -d ’{’ nickname’: ’B.’, ’breed’: ’Australian Kelpie’, ’ age’: 2}’ Um Datensätze eines Buckets abzurufen wird das HTTPVerb GET verwendet: $ curl http://localhost:10018/riak/dogs/bob HTTP/1.1 200 OK X-Riak-Vclock: a85hYGBgzGDKBVIcR4M2cgcs+X4ygymRMY+ V4XJC/Cm+LAA= Link: </riak/dogs>; rel="up" ETag: "4pQlxK0OzKmotRvLkoScsq" Content-Type: application/json ... {"nickname": "B.", "breed": "Australian Kelpie", age : 2} Die Verbindung zwischen zwei Datensätzen innerhalb von Riak geschieht über die explizite Erstellung von Links. Das Schema für die Definition von Links ist folgendermaßen: Link: </riak/[bucket_name]/[key]>; riaktag="[my_tag] " Ein Beispiel für die Erstellung eines Link: curl -X PUT http://localhost:10018/riak/cages/1 -H " Content-Type: application/json" -H "Link: </riak /dogs/wuffy>; riaktag=\"contains\"" -d ’{"room" : 23}’ Nun ist es möglich, diese Links, die in den HTTP-Responses als Header Informationen verschickt werden, zu durchlaufen: curl -i http://localhost:10018/riak/cages/1/_,_,_ Die Syntax: , , ist dabei folgendermaßen zu interpretieren: [bucket name],[tag], [keep]. Es ist somit möglich die Links zwischen Einträgen in der Datenbank auf einen gewissen Bereich einzugrenzen. Durch die Verwendung von mehrfacher Anwendung des Link-Walking kann somit bequem durch den Datenbestand navigiert werden. 3) Map Reduce: Wie viele NoSQL Datenbanken bietet auch Riak eine Möglichkeit an Daten lokal auf den Knoten zu verarbeiten und die aggregierten Ergebnisse dann zusammen zu tragen. Dafür verwendet Riak ein Verfahren namens “Map Reduce”[14], welches ursprünglich von der Firma Google Inc. im Jahre 2004 vorgestellt wurde. Die praktische Verwendung von MapReduce in Riak funktioniert über Javascript. Es werden dabei per HTTP-Request Funktionen mitgeschickt, die in Javascript definieren, was genau bei einem Map bzw. Reduce Schritt ausgeführt werden soll. Alternativ ist es auch möglich, ähnlich wie in relationalen Datenbanken sogennante “Stored Procedures” anzulegen, die diese Javascript Funktionen in der Datenbank persistieren. Dann kann in einem Query per Name auf diese Funktionen zugegriffen werden. Ein Beispiel für eine solche Anfrage lautet: curl -X POST -H "content-type:application/json" http ://localhost:10018/mapred --data @- PUT http://localhost:10018/riak/dogs/bob { oder durch die automatische Vergabe des Keys: POST http://localhost:10018/riak/dogs "inputs":[ ["rooms","23"],["rooms","24"],[" rooms","25"] 4 ], "query":[ {"map":{ "language":"javascript", "source": "function(v) { var parsed_data = JSON.parse(v.values[0].data); var data = {}; data[parsed_data.style] = parsed_data.capacity; return [data]; }" } }] } 4) CAP Theorem in der Praxis: Die Entscheidung bei einer verteilten Datenbank, wie auf eine eintretende Partitionierung des Netzwerkes eingegangen wird, obliegt in der Regel dem Datenbankentwickler. Dieser Entscheidet, ob das DBMS dem C&P bzw. dem A&P Ansatz folgt. Riak verfolgt hier eine interessante Strategie. Grundsätzlich folgt Riak dem A&P Ansatz, allerdings lässt sich der Faktor Konsistenz als Parameter verstehen, der auf einer Pro-Anfrage-Basis variabel ist. Dabei gibt bei Anfragen die drei Parameter N, W und R. N beschreibt die Anzahl Replikate im Cluster, W gibt die notwendige Anzahl von Knoten, bei denen ein erfolgreicher Schreibvorgang stattgefunden hat, an, bis der Schreibvorgang insgesamt als erfolgreich angesehen wurde. Somit gilt für W < N , dass der Schreibvorgang als erfolgreich akzeptiert wurde, auch wenn noch nicht alle Schreibvorgänge abgeschlossen sind. Der Parameter R gibt die Anzahl der Konten an, von denen ein Lesevorgang ausgeführt werden soll. Durch diese Parameter lassen sich verschiedene Konsistenzmodelle herbeiführen: • Eventually Consistency: W + R ∗ N (siehe II-C: BASE) • Consistency by writes: W = N, R = 1 • Consistency by reads: W = 1, R = N • Consistency by quorum: W + R > N Insbesondere die drei letzteren wurden dabei genauer in [15] beschrieben. In Riak können diese drei Parameter per URL bzw. im Body der HTTP Anfrage mitgeliefert werden: curl -X PUT http://localhost:8091/riak/dogs -H " Content-Type: application/json" -d ’{"props":{"w ":2, "n_val":1, "r": 2}}’ IV. S PALTENORIENTIERTE DATENBANKEN Die zweite Kategorie von NoSQL-Datenbanken, auf die hier näher eingegangen wird sind spaltenorientierte Datenbanken. Ihren Ursprung hat diese Datenbank in dem Bereich OLAP (Online Analytical Processing) und ihrer Optimierung. Die wesentliche Eigenschaft von spaltenorientieren Datenbanken ist die zusammenhängende Speicherung der Daten einer Spalte auf dem Speichermedium. Bei relationalen Datenbanksystemen wird hingegen Zeilenweise persistiert. Bei OLAPAnwendungen ist genau diese Art der physikalischen Speicherung von Vorteil, da hier in der Regel Auswertungen betrachtet werden, die sich auf einzelne Spalten und ihre Aggregation beziehen. Es werden dabei meist keine ganze Datensätze (bspw. ein Kundendatensatz) betrachtet, sondern eher einzelne Spalten der gesamten Tabelle (bspw. die Postleitzahlen aller Kunden) um Auswertungen über den gesamten Datenbestand zu erstellen. Die Erzeugung einer Spalte in einem RDBMS ist deutlich aufwendiger und bezieht sich immer auf die gesamte Tabelle. Das ist bei spaltenorienterten Datenbank nicht der Fall. Es kann durchaus eine Spalte in einer Zeile existieren und in der nächsten nicht. Dieses Verhalten kann auch als Mittelweg in Bezug auf das Schema zwischen einer relationalen Datenbank und einem Key-Value Store angesehen werden. Vertreter dieser Kategorie sind u.a. Google BigTable, bzw. dessen Open Source Implementierung: HBase, Apache Cassandra. V. D OKUMENTENORIENTIERTE DATENBANKEN Ähnlich wie Key-Value Stores, speichern dokumentenorientierte Datenbanken zu einem gegebenen Schlüssel einen Wert ab. Allerdings hat dieser Wert eine dokumentenartige Struktur (z.B. ein JSON Dokument). Abgesehen von der gegebenen Struktur des JSON Formates gibt es allerdings keine weiteren Einschränkungen bezüglich der Struktur. So können beliebige valide JSON Dokumente unter verschiedenen Schlüsseln abgelegt werden. Dabei sind auch geschachtelte Strukturen innerhalb des Dokumentes erlaubt. Im Unterschied zu Key-Value Stores hat das DBMS also grundlegende Informationen über die Struktur des Dokuments. Diese Eigenschaft wird dazu genutzt, mehr Abfragelogik in die Datenbank zu bringen und direkt zu verarbeiten. Im Gegensatz zu anderen NoSQL-Kategorien, gibt es bei den dokumentenorientieren Datenbanken mit Lotus Notes schon einen Vertreter, dessen Anfänge in die 80er Jahre zurückreichen. Weitere Datenbankmanagementsysteme in diesem Bereich sind bspw.: MongoDB, CouchDB als auch die Hybrid-DMB Systeme: Apache Cassandra und Redis. Auf einen Vertreter (CouchDB) wird stellvertretend im nachfolgenden Kapitel näher eingegangen. A. CouchDB CouchDB ist eine solche dokumentenorientierte Datenbank, wobei der Name als Akronym für “Cluster of unreliable commodity hardware Data Base” steht. Der Fokus lässt sich somit bereits aus dem Namen erkennen. Statt teurer zuverlässiger Spezial-Hardware ist die Verwendung eines beliebig großen Clusters von Standard-Hardware vorgesehen. Der Entwickler von CouchDB war auch an der Entwicklung von Lotus Notes beteiligt, sodass gewisse Konzepte übernommen wurden, jedoch um heutige Technologien (z.B. Map Reduce) erweitert wurde. Implementiert ist CouchDB, ebenso wie Riak, in Erlang. Auf die wesentlichen Merkmale von CouchDB wird nachfolgend eingegangen. 1) Datenbankkommunikation per HTTP / REST: Genau wie bei Riak wird auch bei CouchDB das HTTP-Protokoll verwendet, um mit der Datenbank zu interagieren. Es verwendet für die verschiedenen CRUD-Operationen die HTTP-Verben. Um Beispielsweise ein einzelnes Dokument abzufragen wird folgender Aufruf verwendet: $ curl http://localhost:5984/music/ ae98eaf98dfef987af6756dfd655e { 5 "_id":"ae98eaf98dfef987af6756dfd655e", "_rev":"4-7123476876ad87e6feda876aa", "name":"Blind Dog", "albums": [ {"title":"The Last Adventures Of Captain Dog", "year":2001 }, ] } Dabei wird eine GET Operation auf die id ae98eaf98dfef987af6756dfd655e ausgeführt. Als Ergebnis erhält man das Dokument. Zusätzlich gibt es zwei weitere id, rev. Diese beiden Eigenschaften Informationen: beschreiben die Identität eines Dokumentes. In CouchDB wird neben der eindeutigen ID eine zusätzliche Revisionssnummer gespeichert. Der Grund für dieses Vorgehen wird in Kapitel V-A3 näher erläutert. Ein neues Dokument kann per HTTP POST auf die Datenbank URL erzeugt werden: $ curl -X POST "http://localhost:5984/music/" -H " Content-Type: application/json" -d ’{ "name": " Eric Clapton" }’ Hier ist bereits zu erkennen, dass CouchDB kein festes Schema für die Dokumente vorsieht. Bei dem obigen Beispiel wurde unter dem Key “albums“ eine Menge von Objekten gespeichert. Dies ist bei dem neu hinzugefügten Dokument nicht der Fall. Bei dem Aktualisieren eines existierenden Datensatzes wird in CouchDB immer das vollständige Dokument mit den aktualisierten Werten übergeben. Dabei ist wichtig, dass die korrekte Revisionsnummer verwendet wird. $ curl -X PUT "http://localhost:5984/music/ ae98eaf98dfef987af6756dfd655e" -H "Content-Type: application/json" -d ’ { "_id": "ae98eaf98dfef987af6756dfd655e", "_rev": "1-7612309098adebbdb12341", "name": "Eric Clapton", "albums": ["Pilgrim", "Edge ", "461 Ocean Boulevard"] }’ Als Rückgabe erhält man, sofern die aktuellste Revisionsnummer verwendet wurde: { "ok":true, "id":"ae98eaf98dfef987af6756dfd655e", "rev":"2-4371093810adef123efea12321b" } eine Erfolgsmeldung mit der neuen Revisionssnummer des Dokuments. Weitere Hintergrundinformationen zum Thema Revisionen und deren Verwendung ist im 2) Verwendung von Views: Views werden in CouchDB, ähnlich wie in relationalen Datenbanksystemen, dazu verwendet die Daten darzustellen. Im Falle von CouchDB sind diese Daten meist Dokumente, die zu neuen aggregierten Dokumenten transformiert werden. Dazu verwendet CouchDB wie Riak den Map-Reduce-Ansatz. Grundsätzlich gibt es in CouchDB die Möglichkeit von ad-hoc Anfragen als auch von vorberechneten Design Dokumenten. Der Unterschied ist im Wesentlichen, dass bei ad-hoc Anfragen die Map-Funktion auf jedes Dokument in der Datenbank ausgeführt wird. Dieses Verhalten schließt einen Einsatz im Produktivbetrieb aus, da die Berechnung von solchen ad-hoc Anfragen extrem langsam sein kann. Die alternative: vorberechnete Design Dokumente werden demnach nicht zum Anfragezeitpunkt ausgewertet, sondern stattdessen vorberechnet. Dieser Geschwindigkeitsgewinn schlägt sich allerdings negativ in der Flexibilität nieder. Ein Design-Dokument enthält typischerweise mehrere Views. Ein Beispiel für einen solchen View ist die Indizierung der Musikdatenbank nach Namen. Dazu kann folgende, in Java Script definierte, Map Funktion verwendet werden: function(document) { if (’name’ in document) { emit(document.name, document._id); } } Diese kann per entsprechender HTTP-POST-Operation auf den CouchDB-Server übertragen werden. Der Reduce Teil des Views ist dabei optional. Mit folgender Anfrage ist da daraufhin möglich diesen View zu betrachten: $ curl ’http://localhost:5984/music/_design/artists/ _view/by_name?key="Eric Clapton"’ { "total_rows":1, "offset":0, "rows":[{ "id":"ae98eaf98dfef987af6756dfd655e", "key":"Eric Clapton", "value":"ae98eaf98dfef987af6756dfd655e" }] } 3) Multiversion Concurrency Control: CouchDB verwendet ein Verfahren namens “Multiversion Concurrency Control”. Es wird, statt ein Dokument bei einem Update zu überschreiben, eine weitere Version dieses Dokumentes gespeichert. Da es nun für eine ID mehrere Dokumente gibt, ist es notwendig, eine Revisionsnummer einzuführen, die innerhalb dieser ID wieder zu Eindeutigkeit führt. Der Hauptgrund für dieses Vorgehen ist, dass dadurch blockierende Schreib- / Lesezugriffe verhindert werden können. Statt die Update-Anfragen verschiedener Benutzer sequentiell abzuarbeiten wird jedes Dokument unter einer anderen Revision persistiert. Dieses Verhalten entspricht in etwa einem Versionsverwaltungssystem, allerdings kann bei CouchDB nicht gewährleistet werden, dass stets alle Versionen verfügbar sind. Durch Komprimierungsvorgänge und Replikation bei großen Datenmengen sind u.U. alte Revisionen nicht dauerhaft verfügbar[16]. CouchDB &ist an dieser Stelle sehr explizit bezüglich Konflikten. Es wird dem Benutzer der Datenbank überlassen, ggf. eine Konfliktbehandlung selbst durchzuführen. Für die Kommunikation wird dabei der entsprechende HTTPStatuscode 409 -(Conflict) verwendet. VI. G RAPHENDATENBANKEN Die letzte und neueste Kategorie im Bereich NoSQL sind Graphendatenbanken. Hier wird für die Repräsentation von Daten ein Graph verwendet. Entsprechend gibt es die Konzepte von Konten und Kanten zwischen diesen Knoten. Sowohl an Kanten als auch an Knoten können Key-Value Paare angehängt werden, die die Daten enthalten. Der besondere Vorteil an Graphendatenbanken ist die Verwendung der vielen graphentheoritischen Algorithmen zum Traversieren von Graphen. Da in einem Graphen beliebige Knoten miteinander 6 verbunden sein können, gibt es normalerweise kein Schema für Graphendatenbanken. Der Einsatzzweck ist immer dort gegeben, wo man in RDBM-Systemen selbst referenzierende Entitäten oder Baumstrukturen vorfindet. Ein Beispiel dafür sind Freundschaftsbeziehungen in sozialen Netzwerken. Vertreter dieser Kategorie sind u.a. Neo4J und BigData. Bezüglich der Anfragesprachen gibt es im Bereich Graphendatenbanken im Gegensatz zu anderen Kategorien der NoSQL Bewegung eine gewisse Konsolidierung, da die Art auf Graphen zuzugreifen sich in den Implementierungen nicht wesentlich unterscheidet. Ein bekannter Vertreter einer solchen Anfragesprache ist die domänenspezifische Sprache “Gremlin”, mit der es möglich ist auf verschiedene Datenbanken aus diesem Umfeld zuzugreifen. A. Semantic Web Datenbanken Eine Unterkategorie der Graphendatenbanken stellt der Bereich der Semantic Web Datenbanken dar. Diese Datenbanken ermöglichen den Zugriff auf Graphen, die aus RDF Triplen bestehen. Die Abfragesprache ist mit SPARQL / SPASQL (SPARQL innerhalb einer SQL Anfrage) allerdings fest definiert. Dieses feste Schema in der Abfrage, aber auch bei der Datenbasis (RDF-Tripel haben immer eine gewisse Struktur), ist der Hauptunterschied zu anderen Graphendatenbanken. VII. Z USAMMENFASSUNG Der Bereich der NoSQL Datenbanksysteme ist äußerst vielfältig. Die einzelnen Kategorien unterscheiden sich im dem Grad, in dem Sie von dem klassischen, relationalen Modell abweichen. Dieser Grad hängt im Wesentlichen von folgenden beiden Eigenschaften ab: • • Kenntnisse über das Schema der Daten Flexibilität der Anfragen Einfache Key-Value Datenspeicher haben wenig Kenntnis über das Schema. Daher sind die Anfragearten gewissermaßen begrenzt. Die Anfragelogik wird in dieser Kategorie in Richtung der verwendenden Anwendung verschoben. Hybridmodelle, wie Spaltendatenbanken oder Dokumentenorientierte Datenbanken gehen hier einen Mittelweg, der einem entweder gewisse Schemastrukturen vorgibt und somit in der Lage ist, mehr Flexibilität in der Anfrage zu ermöglichen. Durch ihre unterschiedlichen Annahmen an Konsistenz (siehe CAP-Theorem) sind viele NoSQL Datenbanken in der Lage Hochverfügbarkeit und ein einfaches horizontales Skalieren zu ermöglichen. Nichtsdestotrotz gibt es auch weiterhin den Bedarf an relationalen Datenbanksystemen. Diese sind insbesondere dann von Vorteil, wenn die genaue Struktur der Daten zu Beginn festgelegt werden kann bzw. eine sehr große Anfrageflexibilität notwendig ist. Zusammenfassend lässt sich sagen, dass NoSQL Datenbanken das relationale Modell keineswegs ersetzen werden. Vielmehr ist es wahrscheinlich, dass diese beiden Welten in Koexistenz innerhalb eines Projektes verwendet werden, um die Vorteile, die beide Ansätze besitzen zu vereinen. L ITERATUR [1] G. DeCandia, D. Hastorun, M. Jampani, G. Kakulapati, A. Lakshman, A. Pilchin, S. Sivasubramanian, P. Vosshall, and W. Vogels. Dynamo: Amazon’s highly available key-value store. [Online]. Available: http://www.allthingsdistributed.com/files/amazon-dynamo-sosp2007.pdf [2] S. Gilbert and N. Lynch. Brewer’s conjecture and the feasibility of consistent, available, partition-tolerant web services. [Online]. Available: http://lpd.epfl.ch/sgilbert/pubs/BrewersConjecture-SigAct.pdf [3] D. E. A. Brewer. Towards robust distributed systems. [Online]. Available: http://www.cs.berkeley.edu/∼brewer/cs262b-2004/ PODC-keynote.pdf [4] ——. Cap twelve years later: How the ”rules”have changed. [Online]. Available: http://www.infoq.com/articles/ cap-twelve-years-later-how-the-rules-have-changed [5] W. Vogels. Eventually consistent - revisited. [Online]. Available: http://www.allthingsdistributed.com/2008/12/eventually consistent.html [6] Memcached official website. [Online]. Available: http://memcached.org/ [7] B. T. Inc. Riak official website. [Online]. Available: http://basho.com/ products/riak-overview/ [8] A. S. Foundation. Apache cassandra official website. [Online]. Available: http://cassandra.apache.org/ [9] Amazon. Amazon dynamo db official website. [Online]. Available: http://aws.amazon.com/de/dynamodb/ [10] Citrusbyte. Redis official website. [Online]. Available: http://redis.io/ [11] G. Inc. Google protocol buffers: An overview. [Online]. Available: https://developers.google.com/protocol-buffers/docs/overview [12] “curl official website.” [Online]. Available: http://curl.haxx.se/ [13] B. T. Inc. Riak bucket explanation. [Online]. Available: http: //docs.basho.com/riak/1.2.1/references/appendices/concepts/Buckets/ [14] J. Dean and S. Ghemawat. Mapreduce: Simplied data processing on large clusters. [Online]. Available: http://static.googleusercontent.com/external content/untrusted dlcp/research.google.com/de//archive/mapreduce-osdi04.pdf [15] E. Rahm, Mehrrechner-Datenbanksysteme: Grundlagen der verteilten und parallelen Datenbankverarbeitung. Addison-Wesley (Deutschland) GmbH, 1994. [16] Versioning docs in couchdb. [Online]. Available: http://jchrisa.net/drl/ design/sofa/ list/post/post-page?startkey= %5b%22Versioning-docs-in-CouchDB%22%5d