Leopold-Franzens-University Innsbruck Institute of Computer Science Research Group Quality Engineering BACHELOR THESIS Effiziente Sessionverwaltung für einen Streamingdienst Mathias Mahlknecht Supervisor: Prof. Dr. Ruth Breu Innsbruck, 15. Januar 2015 Abstract: There are more and more NoSQL database systems on the market and they are a good alternative to relational Databases. One of these NoSQL databases is Couchbase. In this thesis will be discussed how the session management of a big german streaming company has been remade by using the Couchbase database. This became necessary due to the increasing number of users. This thesis describes how Couchbase works and how the new session management has been implemented. 1 Zusammenfassung: Es werden immer mehr NoSQL Datenbanksysteme entwickelt und sie stellen inzwischen eine echte Alternative zu herkömmlichen Relationalen Datenbanken dar. Eine dieser NoSQL Datenbanksysteme ist Couchbase. In dieser Arbeit wird eine Sessionverwaltung für einen großen deutschen Streamingdienst erneuert, in der Couchbase als Cache verwendet wird. Das wurde nötig, um den steigenden Benutzerzahlen gerecht zu werden. Außerdem wird beschreiben wie Couchbase im allgemeinen funktioniert und es wird auf die Umsetzung der Sessionverwaltung eingegangen. 3 Inhaltsverzeichnis Einleitung 9 NoSQL-Datenbanken 1 Was ist NoSQL? . . . . . . . . . . . . . . . . 2 NoSQL vs. Relational . . . . . . . . . . . . . 3 Verschiedene Typen von NoSQL-Datenbanken 3.1 Spaltenorientierte Datenbanken . . . . 3.2 Objektorientierte Datenbanken . . . . 3.3 Graphenorientierte Datenbanken . . . 3.4 Key-Value-Orientierte Datenbanken . 3.5 Dokumentorientierte Datenbanken . . Cache 1 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 11 12 13 13 14 15 15 16 17 Allgemeiner Ablauf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 Cache in Webanwendungen . . . . . . . . . . . . . . . . . . . . . . . . . . 17 Couchbase 1 Architektur . . . 2 Datenspeicherung 3 View und Index . 4 Web Console . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Anforderungen an die Umsetzung 1 Ist-Architektur . . . . . . . . . . . . . . . . . . . . . . . . . . 1.1 REST . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2 EHCache . . . . . . . . . . . . . . . . . . . . . . . . . 1.3 Oracle Datenbank . . . . . . . . . . . . . . . . . . . . 2 Use Cases des Cachingsystem . . . . . . . . . . . . . . . . . . 2.1 Caching der laufenden Sessionen . . . . . . . . . . . . 2.2 Alle wiedergegebenen Titel pro Benutzer . . . . . . . . 2.3 Die letzten 50 wiedergegebenen Titel pro Produkt und 2.4 Bookmarking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Benutzer . . . . . . . . . . 19 19 20 21 22 . . . . . . . . . 25 25 26 27 28 28 29 29 29 30 Umsetzung der Anforderungen 31 1 Session Cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 1.1 Architektur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 5 2 3 4 5 1.2 Weitere Caches Die Listen . . . . . . . 2.1 Architektur . . Bookmarking . . . . . Check and Set (CAS) REST-Schnittstellen . . . . . . . . . . . . . Evaluierung 1 Integrationtests . . . . . . 2 Performance . . . . . . . . 2.1 Benchmarks . . . . 3 Couchbase vs. MongoDB . Zusammenfassung und Ausblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 34 35 36 37 38 . . . . 41 41 41 42 44 47 Abbildungsverzeichnis 1 2 3 Objekte und Tabellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 Spalten- und Zeilenorientierte Datenbanken im Vergleich . . . . . . . . . . 14 Key-Value-Datenbank . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 4 5 6 7 8 Die Grundstrucktur von Couchbase . . . . . . . . . Aufbau des Cochbase Speichers . . . . . . . . . . . Startseite der Cochbase Web Console . . . . . . . . Bucketübersicht der Couchbase Web Console . . . Zugriffsratenübersicht der Couchbase Web Console 9 10 Die Grundstrucktur des Middlelayers . . . . . . . . . . . . . . . . . . . . . 25 Use Cases des Cachingsystem . . . . . . . . . . . . . . . . . . . . . . . . . 28 11 12 13 14 15 Projektübersicht mit erneuerten Teilen Die Klasse für das SessionDokument . Die Architektur des SessionCaches . . Eine Wrapperklasse . . . . . . . . . . . Klassendiagramm der Watchlist . . . . 16 17 Benchmark - Operationen pro Sekunde . . . . . . . . . . . . . . . . . . . . 43 Benchmark - Latency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 20 22 23 24 31 33 33 35 36 7 Aus Gründen der Lesbarkeit wird in dieser Arbeit auf die genderspezifische Schreibweise verzichtet. Sämtliche personenbezogene Bezeichnungen sind geschlechtsneutral zu verstehen. Einleitung NoSQL Datenbanken werden immer populärer. Vor allem in Onlineapplikationen, wo jede Sekunde Tausende von Datenbankoperationen durchgeführt werden müssen, sind sie mittlerweile fast unverzichtbar. Bei richtiger Anwendung sind sie um ein Vielfaches performanter als relationale Datenbanken, außerdem sind sie darauf ausgelegt, auf verteilten Systemen zu laufen und skalieren deshalb gut. Diese Arbeit entstand im Laufe eines Praktikums für das Mailänder IT-Unternehmen Fincons Group. Das Unternehmen entwickelt unter anderem die Software für die Streamingplattform eines großen deutschen Medienunternehmens. Durch die wachsenden Benutzerzahlen war es nötig, die Performance zu erhöhen. Dazu wurde im Laufe des Praktikums der bestehende Cache sowie Teile der relationalen Datenbank entfernt und durch die NoSQL Datenbank Couchbase ersetzt. Zunächst wird im Kapitel NoSQL-Datenbanken erklärt, was eine solche Datenbank ausmacht und was die Unterschiede zu einer relationalen Datenbank sind, außerdem werden die unterschiedlichen Typen von NoSQL-Datenbanken kurz erläutert. Anschließend wird kurz darauf eingegangen, was ein Cache ist, um dann schließlich genauer auf Couchbase einzugehen. Hier wird die Architektur und die Art der Datenspeicherung in Couchbase erklärt. Außerdem werden Views und Indices beschrieben und die Vorteile der graphischen Web Console von Couchbase aufgezeigt. Im Kapitel Anforderungen an die Umsetzung wird zunächst die Ist-Architektur beschrieben, mit der REST-Schnittstelle, EHCache, sowie der Oracle Datenbank. Anschließend wird auf die einzelnen Use Cases dieser Arbeit genauer eingegangen. In Umsetzung der Anforderungen wird beschrieben, wie die Anwendung erstellt wurde. Für jeden Teil wird der Ablauf und die Funktionsweise beschrieben, sowie Probleme beim Erstellen. Außerdem wird auf die Architektur, so wie sie nach dem Beenden der Arbeit war, kurz eingegangen. Im abschließenden Kapitel Evaluierung werden die erfolgten Tests, so wie allgemeine Benchmarks aus der Literatur, beschrieben. Zusätzlich wird Couchbase mit einer anderen bekannten NoSQL-Datenbank verglichen. Dabei handelt es sich um die Dokumentorientierte Datenbank MongoDB. 9 NoSQL-Datenbanken Die Inhalte dieses Kapitels beruhen hauptsächlich auf den folgenden zwei Büchern. Pro” fessional NoSQL“ von Shashank Tiwari [20] und NoSQL Distilled: A Brief Guide to the ” Emerging World of Polyglot Persistence“ von Pramod J. Sadalage und Martin Fowler [17]. 1 Was ist NoSQL? NoSQL“ setzt sich aus den beiden Wörtern No“ und SQL“ zusammen, was so viel ” ” ” bedeutet wie kein SQL“. Dies weist also bereits darauf hin, dass NoSQL-Datenbanken ” eine Alternative zu herkömmlichen relationalen Datenbanken bietet, da relationale Datenbanken als Abfragesprachen meist SQL verwenden. Ein besserer Name wäre vielleicht NoRelational“, da auch NoSQL-Datenbanken teilweise Abfragesprachen zur Verfügung ” stellen, die SQL ähneln. Es hat sich aber die Bezeichnung NoSQL“ durchgesetzt. ” Es gibt keine richtige Definition für NoSQL“, der Begriff fasst einfach alle nicht ratio” nalen Datenbanksysteme zusammen, die sich in ein paar Punkten ähnlich sind. Davon abgesehen können die verschiedenen NoSQL-Datenbanken sehr verschieden sein. Es gibt dann mehrere Untergruppen für jeweils ähnliche NoSQL-Datenbanken, auf diese wird aber später noch genauer eingegangen. Wie bereits erwähnt ist eines der Hauptcharakteristika, dass nicht das relationale Modell verwendet wird. Es geht sogar so weit, dass überhaupt kein Schema vorgegeben wird. So können auch komplexere Datentypen, wie Listen, einfach abgespeichert werden. Außerdem kann sich die Form der Daten jederzeit ändern, ohne dass das größere Auswirkungen auf die Datenbank hätte und die einzelnen Daten müssen auch nicht alle in die selbe Form gepresst werden. Ein weiteres wichtiges Merkmal ist, dass NoSQL-Datenbanken einfach auf verteilten Systemen laufen. Die Datenbanken sind auf sehr große Datenmengen und hohe Zugriffsraten optimiert und die Cluster können im laufenden Betrieb vergrößert oder verkleinert werden, ohne dass das Auswirkungen auf die Anwendungen hat. Natürlich birgt das auch Nachteile. So wird zum Beispiel das ACID-Prinzip von den meisten Datenbanken nicht mehr voll unterstützt. Des weiteren werden NoSQL-Datenbanken fast ausnahmslos unter einer Open Source Lizenz zur Verfügung gestellt. Sie wurden alle im letzten Jahrzehnt entwickelt und an die Neuheiten des Webs des 21. Jahrhunderts angepasst. 11 2 NoSQL vs. Relational Relationale Datenbanken bilden alle Daten auf Tabellen ab. Das führt dazu, dass manche Objekte auf unnatürliche Weise aufgeteilt werden müssen, wie in Abbildung 1 gezeigt wird. In NoSQL-Datenbank ist dies meist nicht der Fall, hier können die Daten, so wie sie auf natürliche Weise zusammen gehören, abgespeichert werden. Das geschieht zum Beispiel als Objekte oder Dokumente. Die Abfragen erfolgen immer mit SQL, so können auch die Inhalte von mehreren Tabellen kombiniert werden. Dies ist nötig um die Daten, die auf verschiedene Tabellen verteilt sind, wider zusammen zu fügen. Eine solche Abfragesprache wird in den NoSQL-Datenbanken meist vermisst. Obwohl meist alle zusammen gehörenden Daten in dem selben Dokument abgespeichert werden, ist es oft nötig die Daten von mehren Dokumenten zu kombinierten. Aus diesem Grund wird immer mehr versucht, auch für NoSQL-Datenbanken solche Abfragesprachen zu entwickeln. Dies ist jedoch nicht so einfach, wegen der Art, wie die Daten in NoSQL abgebildet werden. Außerdem kann es auch gewisse Auswirkungen auf die Performance haben, da die Daten meist sehr stark verteilt sind. Abbildung 1: In relationalen Datenbanken werden Objekte oft auf unnatürliche Weise aufgeteilt, während in NoSQL die Objekte oft einfach als solches abgespeichert werden können.[17] Ein weiterer großer Unterschied ist, dass NoSQL das ACID-Prinzip nicht voll unterstützt. Im relationalen System ist es mithilfe von Transaktionen möglich, Blöcke von Befehlen als atomar zu betrachten. Das wird normalerweise gemacht, um logische Konistenz zu garantieren. In NoSQL gibt es so etwas wie Transaktionen nicht, deshalb ist prinzipiell nur jeder Befehl für sich atomar, es ist jedoch nicht so einfach möglich eine Befehlskette als atomar zu definieren. Die verschiedenen NoSQL-Datenbanken gehen nicht alle gleich damit um. Manche bieten gar keine Alternative und gehen einfach davon aus, dass dieses Problem sehr selten auftritt, da die Daten anders abgespeichert werden als in relationalen Datenbanken und so normalerweise alle zusammen gehörenden Daten in einem Dokument abgespeichert werden. Andere versuchen zum Beispiel mit so genannten CAS-Befehlen (check-and-set), das Problem zu umgehen. Darauf wird im Kapitel 4 noch genauer eingegangen. Während relationale Datenbanken immer eine starke Konsistenz garantieren, ist das durch die starke Verteilung bei NoSQL-Datenbanken nicht leicht möglich. Deshalb werden viele NoSQL-Datenbanken als eventually consistent bezeichnet. Das bedeutet, es wird nur garantiert, dass die Datenbank irgendwann konsistent ist, aber nicht zu einem bestimmten Zeitpunkt. Meist wird auch sequenzielle Konsistenz garantiert. Auch hier spielen die CAS-Befehle eine wichtige Rolle. Außerdem ist es oft möglich, sofortige Konsistenz für bestimme Operationen zu erzwingen, was aber große Auswirkungen auf die Performance hat. Generell wird hier eine gewisse Verantwortung dem Entwickler überlassen. Dieser kann dann selbst entscheiden, welches Verhältnis von Sicherheit und Performance für seine Anwendung benötigt wird. In NoSQL wird auch das durability constraint abgeschwächt. Während relationale Datenbanken als streng dauerhaft definiert werden, verzichten viele NosQL-Datenbanken teilweise darauf, auch hier aufgrund von Performance. So werden die Daten oft zunächst in den Hauptspeicher übernommen und erst nach und nach auf die Platte geschrieben. Einige Datenbanken verzichten sogar komplett auf die Persistenz. Generell gehen aber die verschiedenen Datenbanksysteme damit unterschiedlich um. 3 Verschiedene Typen von NoSQL-Datenbanken 3.1 Spaltenorientierte Datenbanken Die spaltenorientierten Datenbanken sind den relationalen Datenbanken am ähnlichsten. Der Unterschied liegt hauptsächlich in der Art, wie die Daten auf der Platte abgelegt werden. Relationale Datenbanken legen die Daten zeilenweise ab, wie in Abbildung 2c dargestellt ist. Spaltenorientierte Datenbanken legen die Daten spaltenweise ab, wie man in den Abbildungen 2a und 2b sehen kann. Welche der Varianten besser ist, liegt vor allem an der Art der Abfragen die später erfolgen sollen. Gibt es viele Aggregatfunktionen und Operationen die sich jeweils auf nur (a) mit virtueller ID (b) mit expliziter ID (c) relationales System Abbildung 2: (a) und (b) zeigen die zwei Arten, wie spaltenorientierte Datenbanken Daten abspeichern können. (c) zeigt zum Vergleich wie normale relationale Datenbanken ihre Daten ablegen [8] ein Attribut beschränken, aber auf sehr viele Tupel angewendet werden, ist die spaltenorientierte Speicherung effizienter, da die geholten Blöcke auch nur Daten enthalten die benötigt werden. Generell gilt, je größer die Menge der Daten, desto effizienter sind spaltenorientierte Datenbanken. [8] Man unterscheidet zwischen expliziter (Abbildung 2b) und virtueller (Abbildung 2a) ID. Die explizite ID ist die einfachere Variante, hier wird jedem Eintrag auch die ID des dazugehörigen Tupels beigefügt. Da diese Vorgehensweise aber die Größe der Daten im Speicher aufbläht und die Zugriffszeit vergrößert, wurde eine neue Variante entwickelt, die auf die Angabe des IDs verzichtet. Hier bekommen alle Spalten eine fixe Länge, so ist es einfach, die verschiedenen Attributwerte eines Tupels zu finden. Andere Varianten gehen noch weiter und verzichten auch auf die fixe Länge.[15] Diese sind aber nicht trivial und gehen über den Fokus dieser Arbeit hinaus. 3.2 Objektorientierte Datenbanken Im relationalen Datenbankmodell werden die Daten auf Tabellen verteilt. So werden zum Beispiel bei einer Datenbank über Personen Details wie Telefonnummern, Adresse oder genauere Angaben über der den Job auf verschiedene Tabellen verteilt. In der objektorientierten Programmierung hingegen werden die Daten alle in einem Objekt gehalten. Also werden die Daten von der Datenbank und der Anwendung auf verschiedene Weise betrachtet. Dieser Unterschied wird impedance mismatch genannt. Es wird hier also eine weitere Schicht benötigt, die die Daten von einer Ansicht in die andere umwandelt.[18] Um das zu Umgehen wurde die objektorientierte Datenbank entwickelt. Sie speichert die Daten genau so, wie sie die Anwendung verwendet, als Objekte. So kann sich die Anwendung die Daten direkt aus der Datenbank holen. Dadurch wird es möglich auch eigene Datentypen zu definieren und es gibt Listen und Mengen, genau wie die Objekte in den Programmiersprachen der 5. Generation. So kann die Datenbank einfach als persistente Version der Anwendung gesehen werden und nicht mehr als externer Service. Es lassen sich auch Methoden definieren, die bestimmte Abfragen möglicherweise schneller bewältigen können als über die Abfragensprache.[18] 3.3 Graphenorientierte Datenbanken Diese Datenbankmodelle sind vor allem dann nützlich, wenn die Daten sehr stark untereinander vernetzt sind und die Beziehungen gleich wichtig oder sogar wichtiger als die Daten selbst sind. Es können Abfragen direkt auf die Beziehungen gemacht werden und durch die verschiedenen Graphoperationen sind die Datenbanken für diese Art von Aufgaben auch sehr performant. [9] Das Semantic Web [10] kann als eine solche graphenorientierte Datenbank gesehen werden. Hier werden die Beziehungen in bestimmten Wörterbüchern definiert, so kann auch eine Maschine die Inhalte verstehen und erweitern. 3.4 Key-Value-Orientierte Datenbanken Eine Key-Value-Orientierte Datenbank ist die einfachste Art von Datenbank, was den Umfang der API betrifft. Die Daten werden als binäre Blobs abgelegt, die Datenbank selbst weiß also nicht, welche Art von Daten es sind. Über einen eindeutigen Schlüssel werden die Daten angesprochen. Es können also nur Operationen wie get(), put(), delete() oder update() durchgeführt werden. Oft können die Key-Value-Paare noch in verschiedenen Paketen verpackt werden, um verschiedene Arten von Daten von einander zu trennen, so wie in Abbildung 3 dargestellt.[17] Abbildung 3: Das Bucket ist das Paket, das alle Daten der User beinhaltet, über den Key werden die Daten angesprochen und der Value enthält die tatsächlichen Daten. [17] Das in Abbildung 3 benutzte Beispiel der Session pro User, ist typisch für Key-ValueDatenbanken, da hier der User natürlicherweise über seine Session-ID angesprochen wird. Generell eignet sich diese Art von Datenbank gut für Aufgaben, wo die Daten nur über einen Wert angesprochen werden.[17] Nicht zu empfehlen ist die Key-Value-Datenbank, wenn die Daten untereinander in Beziehung stehen, oder Abfragen auf mehrere Daten zugleich gemacht werden sollen. Auch für Abfragen auf den Inhalt der Daten ist diese Datenbank nicht geeignet. [17] 3.5 Dokumentorientierte Datenbanken Im Gegensatz zu Key-Value-Datenbanken ist hier der Inhalt der Daten bekannt, da sie in einem bestimmten Format abgespeichert werden. Welches Format ist nicht wichtig, dabei kann es sich um XML, JSON, BSON oder andere handeln. Die Daten in einem solchen Format werden Dokumente genannt. Ein Dokument kann ganze Listen von anderen Dokumenten enthalten, wie im Listing 2.1 dargestellt. Listing 2.1: Beispeil eines JSON-Dokuments in MongoDB [17] 1 { "firstname": "Pramod", "citiesvisited": [ "Chicago", "London", "Pune", " Bangalore" ], "addresses": [ { "state": "AK", "city": "DILLINGHAM", "type": "R" }, { "state": "MH", "city": "PUNE", "type": "R" } ], "lastcity": "Chicago" 2 3 4 5 6 7 8 9 10 11 12 13 14 15 } Jetzt ist es möglich auch komplexere Abfragen über die Daten in den Dokumenten zu machen. Des weiteren kann in vielen dokumentorientierten Datenbanken ein Index über ein bestimmtes Attribut im Dokument erstellt werden, um so gewisse Abfragen zu beschleunigen. Die in dieser Arbeit verwendete Datenbank Couchbase [3] setzt sich aus einer KeyValue-Datenbank und einer dokumentorientierten Datenbank zusammen. Deshalb wird auf diese beiden Datenbanksysteme im Laufe der Arbeit noch genauer eingegangen. Cache Ein Cache ist ein temporärer Zwischenspeicher, der um ein vielfaches schneller ist als der normale Speicher. Wenn Daten aus dem Speicher geholt werden, werden sie in diese Zwischenspeicher geschrieben und dort für einen bestimmten Zeitraum gehalten. Das hat den Vorteil, dass Daten, die öfters benötigt werden nicht jedes Mal aus dem Speicher geholt werden, müssen und so der Programmablauf nicht unnötig verlangsamt wird. 1 Allgemeiner Ablauf Im Allgemeinen befindet sich der Cache zwischen dem Haubtspeicher und dem Prozessor. Bei einer Speicheranfrage wird zuerst der Cache durchsucht und erst wenn die Daten im Cache nicht vorhanden sind, werden sie aus dem langsameren Haubtspeicher geholt[1]. Wenn eine Abfrage die Daten nicht im Cache finden kann, wird das als cache miss bezeichnet. Dem gegenüber steht der page fault. Das bedeutet, dass die Daten zwar im Cache vorhanden sind, aber nicht mehr im Hauptspeicher. Sie sind also veraltet. Löst eine Abfrage einen cache miss aus, werden die Daten aus dem Hauptspeicher geholt und im Cache abgelegt, so sind sie bei der nächsten Abfrage verfügbar. Bei einem page fault hingegen werden die Daten aus dem Cache entfernt.[1] 2 Cache in Webanwendungen Bei Webanwendungen hat der Client sehr oft einen eigenen Cache, wo Daten, die vom Server geholt werden, zwischengespeichert werden. Dadurch können die Anfragen an den Server minimiert werden. Das entlastet den Server und erhöht die Performance des Programms, da die Daten dann lokal verfügbar sind. Aber auch auf der Serverseite gibt es Caches. Diese können zum Beispiel Ergebnisse von Berechnungen speichern, die sehr oft durchgeführt werden. Das spart Rechenzeit und Rechenleistung. Des weiteren können Daten gecached werden, die vom Server von einer externen Datenbank abgefragt werden müssen. So kann die Übertragungszeit verkürzt werden. Der Cache kann durch zwei verschiedene Arten aktualisiert werden. Entweder durch Pushnachrichten oder durch Pullnachrichten. Beim Push werden Änderungen automatisch 17 vom Server an den Client geschickt. Beim Pull fragt der Client selbst regelmäßig nach, ob die Daten im Cache noch aktuell sind. Im Allgemeinen ist der Cache ein sehr wichtiges Hilfsmittel. Mit ihm kann die Performance sehr einfach, stark erhöht werden. Couchbase In diesem Kapitel wird die NoSQL Datenbank Couchbase vorgestellt. Es soll ein grober Überblick über die Funktionalität gegeben werden, damit später auf die direkte Anwendung von Couchbase in dieser Arbeit, eingegangen werden kann. Für dieses Kapitel wurden hauptsächlich das Buch Developing with Couchbase Server“ von Martin C. ” Brown [12] und die offizielle Website von Couchbase [3], als Quellen herangezogen. Couchbase ist aus dem beiden NoSQL Datenbanksystemen Memcached [5] und CouchDB [4] zusammengesetzt. Mencached ist eine Key-Value- Orientierte Datenbank und CouchDB eine Dokument-Orientierte Datenbank. Dadurch werden die Vorteile der beiden NoSQL Typen vereint und der Entwickler hat die freie Auswahl, welche Funktionen er benutzen will und welche für seine Anwendung nicht von Nutzen sind. 1 Architektur Abbildung 4: Architektur von Couchbase - Die Daten werden auf die Knoten verteilt und die Replikas werden auf den jeweils anderen Knoten gespeichert.[3] Couchbase Server ist als Cluster aufgebaut. Wie in Abbildung 4 zu sehen ist, sind alle Knoten des Clusters gleichberechtigt und die Daten sowie die Replikas werden gleichmäßig auf die Knoten verteilt. Der Entwickler braucht sich darum nicht zu kümmern, 19 da die Verteilung vollautomatisch funktioniert. Falls es nötig wird, das Cluster zu erweitern kann bei laufendem Betrieb ein weiterer Knoten hinzugefügt werden. Daraufhin wird ein Rebalancing durchgeführt, was die Daten neu auf die Knoten verteilt. Dasselbe gilt für das Entfernen eines Knotens. Jeder Knoten besteht aus einer Cache- und einer Persistenzschicht. Innerhalb vom Couchbase Server werden die Daten in Buckets zusammengefasst. Ein Bucket ist eine logische Struktur, die es ermöglicht, Daten voneinander zu trennen. So hat jedes Bucket seine eigenen RAM-Anteile, Replica und Plattenspeicher. Das ist deshalb sinnvoll, da es möglich ist, dass mehrere Applikationen denselben Couchbase Server nutzen. Es ist auch möglich, für eine Applikation mehrere Buckets zu erstellen. Es muss aber beachtet werden, dass jedes zusätzliche Bucket die benötigte Rechenleistung erhöht. Als Cache wird Memcached [5] verwendet. Alle Grundoperationen greifen auf den Cache zu. Wird ein Dokument abgelegt, wird es zuerst im Cache gespeichert und erst später persistent auf der Platte gespeichert. 2 Datenspeicherung Abbildung 5: Das Speichersystem aufgebaut.[12] von Couchbase ist in mehreren Schichten Da Couchbase eine Dokumentenorientierte Datenbank ist, werden alle Daten als Dokumente abgelegt. Jedes Dokument bekommt eine eindeutige ID, worüber auf das Dokument zugegriffen werden kann. Die Daten können in jedem beliebigen Format gespeichert werden. Es wird aber JSON empfohlen, da so das Erstellen von Views (Siehe Unterkapitel 3, View und Index) möglich ist. Für den Großteil der Aufgaben kommt man mit den Grundoperationen aus. Diese greifen, wie in Abbildung 5 dargestellt, zunächst auf den Cache zu. Deshalb bewirken diese Operationen eine sofortige Konsistenz der Daten. Anschließend werden die veränderten Daten in der write Queue“ abgelegt und daraus persistent gespeichert. Der Index für ” die Views wird erst zum Schluss aktualisiert. Die Grundoperationen können wie in Tabelle 4.1 dargestellt, in die vier Typen Create, Read, Update und Delete aufgeteilt werden. Alle diese Operationen sind atomar, das bedeutet, dass sie entweder erfolgreich ausgeführt werden, oder überhaupt nicht. Außerdem ist es möglich, Daten mit einem TTL-Wert (time-to-live) zu speichern, dann werden die Daten nur für eine bestimmte Zeit im Speicher gehalten. Operation CREATE READ UPDATE DELETE Beispiel add(DocumentID, DocumentValue) get(DocumentID) replace(DocumentID, DocumentValue) delete(DocumentID) Befehle add(), set() get() replace(), incr(), decr(), append(), prepend(), cas() delete() Tabelle 4.1: Die Grundoperationen von Couchbase. 3 View und Index Für komplexere Aufgaben gibt es die Views. Sie ermöglichen dem Entwickler, die unstrukturierten Daten in eine fixe Form zu bringen, um sie für eine bestimmte Abfrage vorzubereiten. Dies ist aber nur möglich, wenn die Dokumente im JSON-Format abgelegt sind. Die Views arbeiten mit Map/Reduce Funktionen, Map bringt die Daten in die neue Sturktur und Reduce vereinfacht sie und fasst sie zusammen. Map/Reduce ist eigentlich ein teuerer Vorgang, da die Operationen jedes mal auf die gesamten Daten angewendet werden müssen. Um das zu verhindern, gibt es in Couchbase Indizes. Nach dem Erstellen der Views werden die Map/Reduce Funktionen ausgeführt und ein Index auf die verarbeiteten Daten gebildet. Wenn sich dann Daten ändern, wird der Index aktualisiert und die Map/Reduce Funktionen werden nur auf die veränderten Daten erneut ausgeführt. Views werden in Javascript verfasst, so wie im Listing 4.2 dargestellt. Die Parameter doc und meta beinhalten das Dokument und die dazugehörigen Metadaten. In der Funktion können alle Javascript Operationen verwendet werden, wie zum Beispiel eine If-Anweisung. Mit emit wird der Index erstellt, der erste Parameter bezeichnet den neuen Key und der zweite Parameter den dazugehörigen Wert. Im Listing 4.2 werden alle Dokumente vom Typ Series“ indiziert. Als neuer Key wird title“ verwendet und als ” ” Wert null“. Diese View kann jetzt für ein Query benutzt werden, das nach allen gespei” cherten Serientiteln sucht. Dass als Wert null“ verwendet wird ist nicht ungewöhnlich, ” da oft einfach kein zweiter Wert benötigt wird. Listing 4.2: Beispiel einer View Funktion 1 2 3 4 5 6 7 function (doc, meta) { if(doc.type == "Series") { emit(doc.title, null); } } 4 Web Console Abbildung 6: Die Startseite der Cochbase Web Console[3] Couchbase bietet eine mächtige Web Console, wo einfach und sehr intuitiv alle Servereinstellungen getätigt werden können. In Abbildung 6 ist die Startseite zu sehen, hier hat der Administrator einen guten Überblick über den Status der Server, sowie die Auslastung von Plattenspeicher und RAM. In der Bucketübersicht (Abbildung 7) können neue Buckets erstellt werden. Außerdem sind weitere Details zu allen Buckets abgegildet. Neben der Speichergröße, kann auch die Anzahl der Dokumente und die Operationen pro Sekunde für jedes Bucket abgelesen werden. Mit einem Klick auf Dokuments werden alle Dokumente dargestellt und kleine Dokumente können direkt bearbeitet werden. In Views sind alle Views aufgelistet und es können auch neue erstellt werden. Abbildung 7: Die Bucketübersicht der Couchbase Web Console [3] Mit einem Klick auf ein Bucket wird eine Übersicht mit vielen Graphen, wie in Abbildung 8 geöffnet. Hier sind die Zugriffsraten der verschiedenen Operationen übersichtlich dargestellt. Des weiteren können in der Web Console die Größe der Buckets verändert werden oder Server zum Cluster hinzugefügt oder daraus entfernt werden. Die Web Console bietet noch viele weitere Einstellungsmöglichkeiten, für weitere Details wird auf die Webseite von Couchbase [3] verwiesen. Abbildung 8: Die Zugriffsratenübersicht der Couchbase Web Console eines Buckets[3] Anforderungen an die Umsetzung Der Streamingdienst, der in dieser Arbeit optimiert werden soll, ist bereits in Produktion. Aber durch die steigenden Benutzerzahlen und immer höheren Zugriffsraten gelangt das bestehende Cachingsystem an seine Grenzen. In diesem Kapitel wird zunächst das bestehende System vorgestellt, anschließend wird auf die Anforderungen zur Umsetzung der Aufgabenstellung eingegangen. 1 Ist-Architektur Abbildung 9: Architektur des Middlelayers - Die dunkel hervorgehobenen Teile werden erneuert. Bei dem Programm handelt es sich um eine Art Middlelayer für den Streamingdienst. Auf der Frontend-Seite stehen verschiedene Clientprogramme. Es gibt mehrere Produkte für verschiedene Plattformen. Bei den Produkten gibt es Pakete mit verschiedenen Inhalten die gespreamt werden können. So es zum Beispiel Angebote bei denen nur Sport geschaut 25 werden kann, bei anderen können wiederum nur Spielfilme abgespielt werden. Es gibt noch einige weitere Produkte, außerdem können alle Produkte frei kombiniert werden. Es gibt zur Zeit Clientprogramme für die Plattformen Web, iOS, Android und Xbox. Auf der Backend-Seite stehen die Datenbanken und die dazugehörige Software. Hier werden die Streamingangebote und die Benutzerdaten verwaltet. Dieser Teil wurde von einer dritten Partei entwickelt und wird auch weiterhin betreut. Da dieses System mit den Anforderungen für diesen Streamingdienst nicht kompatibel ist und es auch für die verschiedenen Plattformen verschiedene Anpassungen der Daten benötigt, wurde der Middlelayer entwickelt. Dieser Middlelayer kommuniziert mittels REST [16] sowohl mit dem Clientprogrammen, also auch mit dem Backend. Bei REST handelt es sich um eine Vorgehensweise bei der die gesamte Kommunikation über das HTTP-Protokoll [13] stattfindet. Dies hat den großen Vorteil, dass auch zwischen verschiedenen Plattformen oder Programmiersprachen einfach und problemlos kommuniziert werden kann. Das Programm ist Client und Server zu gleich. Er ist Server für die Clients der verschiedenen Plattformen, über die die Benutzer die Filme streamen. Er ist aber auch Client gegenüber dem Backend, das die ganzen Datenbanken verwaltet. Für die Verbindung zu diesem Backend wurde ein Cache eingerichtet. In der ursprünglichen Version wird das EHCache Framework [19] verwendet. Dieses wird im Laufe dieser Arbeit durch eine Couchbase Datenbank ersetzt. Weiters wird die Funktionalität des Caches erweitert. Der Middlelayer verfügt außerdem über eine Oracle Datenbank [11] in der verschiedene Daten gespeichert werden, die vom Middlelayer benötigt werden. Das sind zum Beispiel verschiedene Listen von bereits gesehen Titeln pro Benutzer oder Daten über die verwendeten Plattformen zum Erstellen von Statistiken. Diese Tabellen werden ebenfalls, so weit es sinnvoll ist, entfernt und durch Couchbase Buckets ersetzt. 1.1 REST Bei der Kommunikation über REST werden die Daten im XML-Format oder als JSONNotation übermittelt. Diese sind unabhängig von der benutzten Programmiersprache und können einfach geparst werden. Dadurch können auch Programme einfach kommunizieren, die in verschiedenen Programmiersprachen geschrieben wurden. Es wird das HTTP-Protokoll verwendet, um die Befehle zu formulieren. Es gibt vier Befehle, POST, PUT, GET und DELETE. Jeder wird für eine bestimmte Art von Aufgabe verwendet [16]: • POST wird für das Erstellen eines neuen Objektes verwendet • PUT wird für das Verändern und Updaten eines bestehenden Objektes verwendet • GET wird für eine Abfrage verwendet • DELETE wird für das Löschen eines Objektes verwendet In diesem Programm wird hauptsächlich JSON verwendet. XML wird aber auch noch unterstützt, da ältere Clientversionen noch mittels XML kommunizieren. Der REST Befehl für den LogIn hat dann folgende Form: 1 GET login?customerCode=${customer}&password=${password}& deviceId=${deviceId}&platform=${platform}&product=${product} &version=${version} Das Fragezeichen markiert den Beginn der Variablen. Die mit dem Ampersand gekennzeichneten Wörter, zum Beispiel customerCode, sind die Variablennamen im Programm. Die mit dem Dollarzeichen markierten und in geschwungene Klammern gesetzten Wörter, zum Beispiel customer, sind die Namen der Variablen im JSON beziehungsweise im XML Dokument. Das JSON Dokument zu dieser Abfrage sieht dann wie folgt aus: 1 { "customer": "password": "deviceId": "platform": "product" : "version" : 2 3 4 5 6 7 8 "1234567", "8a3CA4eBNXw==", "7654321", "iPad", "SG", "64" } 1.2 EHCache EHCache ist ein Framework zum Cachen von Daten. Es liegt verteilt auf einem Server Array. Dadurch kann hohe Performance, Erreichbarkeit und Skalierbarkeit garantiert werden [19]. Es hat eine einfache API zum Speichern und Abrufen von Daten. In einer XML-Datei werden alle allgemeinen Einstellungen festgelegt, wie die Größe des Speichers und die Zeit, wie lange ein Objekt gehalten werden soll. Alle Objekte die gecached werden sollen, werden zuerst in einem eigen Objekt Element, zusammen mit einem Key, gekapselt und dann gespeichert. Über den Key kann ein Element wieder aus dem Cache geholt werden [19]. Ein Element ist eine spezielle Klasse der EHCache API. Darin müssen alle Objekte gekapselt werden, die im Cache abgelegt werden sollen. EHCache wurde in diesem Programm hauptsächlich zum Cachen von Sessionen und Daten der eingeloggten Benutzer verwendet. Im Laufe dieser Arbeit wurde es komplett entfernt und durch Couchbase ersetzt. 1.3 Oracle Datenbank Die Oracle Datenbank [11] ist eine relationale Datenbank die mit SQL bedient werden kann. Auf die allgemeine Struktur von relationalen Datenbanken wurde bereits im Abschnitt 2 eingegangen. In Programm wurde sie verwendet, um mehrere Listen der Benutzer zu speichern. Diese Listen enthielten zum Beispiel alle gesehenen Titel pro Benutzer. Dieser Teil wurde entfernt und Couchbase übernimmt nun diese Funktion, da Couchbase sich gut dafür eignet und auch performanter ist, als die Oracle Datenbank. Des weiteren enthält die Datenbank einige Funktionen, die automatisch Tabellen mit statistischen Daten erstellen, wie die Anteile der verschiedenen iOS-Versionen. Dieser Teil wurde auch in dieser Arbeit in der Oracle Datenbank belassen, da Couchbase für diese Art von Aufgaben nicht ausgelegt ist, und eine relationale Datenbank dafür besser geeignet ist. 2 Use Cases des Cachingsystem Im Folgenden wird auf die Use Cases genauer eingegangen, die mithilfe von Couchbase realisiert werden sollen. Die folgenden Unterkapitel beziehen sich alle auf das Use Case Diagramm in Abbildung 10. Wobei das Unterkapitel 2.1 sich auf Login/Logout bezieht, die beiden Listen der Unterkapitel 2.2 und 2.3 auf gesehene Titel abfragen und das Unterkapitel 2.4 auf Titel stoppen/ wieder abspielen. Abbildung 10: Die drei Haupt-Use-Cases des Cachingsystems 2.1 Caching der laufenden Sessionen Bei jedem Login werden die Benutzerdaten vom Backend angefragt und es wird ein Bean erstellt. Darin sind alle Daten über die aktuelle Session des Benutzers, sowie allgemeine Daten über den Benutzer gespeichert. Diese Beans werden in der Couchbase Datenbank gespeichert. Dies ist sinnvoll, da diese Daten zur Bearbeitung von fast jeder Anfrage des Clients benötigt werden. Würden die Daten nicht gecached, müssten bei jeder Abfrage die Daten erneut von Backend mittels REST übermittelt werden. Das würde die Performance des Programms erheblich beeinträchtigen. Bei dem Logout wird das Bean wieder aus der Datenbank entfernt. Dieser Datenbankeintrag wird außerdem zur Überprüfung von Doppellogins benutzt. Bei einem Login wird zuerst überprüft, ob bereits ein Eintrag in der Datenbank vorhanden ist, was bedeutet, dieser Benutzer hat gerade eine Session laufen, möglicherweise auch auf einem anderen Gerät. Ist das der Fall wird das dem Benutzer mitgeteilt. Der Benutzer hat nun die Möglichkeit, die bereits laufende Session zu beenden, oder er verzichtet auf den Login. 2.2 Alle wiedergegebenen Titel pro Benutzer Für jeden Benutzer wird eine Liste erstellt die alle wiedergegebenen Titel beinhaltet. Sie wird in der Couchbase Datenbank gespeichert und mit dem Benutzernamen verknüpft. Um Redundanz zu vermeiden, werden die Details der Titel in einem eigenen Bucket gespeichert und darauf referenziert. Durch diese Liste hat der Benutzer einen genauen Überblick über die Titel, die er bereits angesehen hat. Außerdem wird diese Liste für statistische Auswertungen verwendet. 2.3 Die letzten 50 wiedergegebenen Titel pro Produkt und Benutzer Da verschiedene Produkte freigeschaltet werden können, ist es nützlich für jedes Produkt eine weitere Liste anzulegen. Diese Listen werden ebenfalls in der Couchbase Datenbank gespeichert. Die Liste wird aber nicht nur mit dem Benutzernamen verknüpft, sondern zusätzlich noch mit dem Produkt. Auch diese Liste hat nicht die gesamten Details der Titel direkt gespeichert, sondern verweist auf das oben genannte Bucket der Titel. Um die Liste aktuell zu halten, werden maximal 50 Titel pro Liste gespeichert. Dadurch sieht der Benutzer von welchem Produkt die gesehenen Titel kommen und es lässt sich gut ermitteln welches Produkt am meisten genutzt wird. So kann der Benutzer seine Produkte so kombinieren, wie es für ihn am sinnvollsten ist und das Unternehmen hat einen guten Überblick darüber welche Produkte am häufigsten in Anspruch genommen werden. 2.4 Bookmarking Die Bookmarkingfunktion speichert, wo der Benutzer einen Titel unterbrochen hat, so kann der Titel in einer späteren Session an dieser Stelle weiter abgespielt werden. Diese Bookmarkingfunktion ist bis jetzt auf der Clientseite implementiert. Das hat aber den Nachteil, dass sie auf die jeweilige Plattform beschränkt ist. So kann zum Beispiel ein im Webclient gestarteter Titel nicht automatisch auf dem Smartphone fortgesetzt werden. Deshalb soll die Funktion auf den Middlelayer verlegt werden, und die Daten sind unabhängig von der Plattform gespeichert. Es wird ein Entrag in der Couchbasedatenbank erstellt. Dieser beinhaltet einen Verweis auf den Titel und auf den Benutzer, sowie einen Zeitstempel, der die Stelle markiert, an der der Titel unterbrochen wurde. Umsetzung der Anforderungen In Laufe der Umsetzung wurde aus dem existieren Projekt das gesamte EH-Cache Framework entfernt, sowie ein Großteil der Oracle SQL-Datenbank. An deren Stelle wurde Couchbase Server verwendet, um die Daten zu speichern. In Abbildung 11 ist noch ein mal das gesamte Projekt abgebildet. Die rot markierten Teile wurden komplett ersetzt und die orange markierten Teile wurden teilweise überarbeitet und angepasst. Abbildung 11: Projektübersicht it erneuerten Teilen - Die rot markierten Teile wurden komplett ersetzt, die orange markierten Teile wurden überarbeitet und angepasst. 1 Session Cache Der Session Cache dient zum Cachen von laufenden Sessionen. Es werden beim Login alle Benutzerdaten aus dem Backend geholt und so lange im Cache behalten, bis sich der Benutzer wieder abmeldet. Das erfolgt zum einen aus Performancegründen, da so nicht bei jeder Abfage zu Benutzerdaten eine Verbindung mit dem Backend aufgebaut werden muss. Des weiteren kann dieser Cache dazu benutzt werden, um zu ermitteln ob 31 ein bestimmter Benutzer bereits angemeldet ist oder nicht. Das hilft zu verhindern, dass ein Benutzer mehrere Sessionen gleichzeitig laufen hat. In der ersten Ausführung wurde ein Dokument pro Sessionkey erstellt und gespeichert. Die verschiedenen Daten sollten mittels Views abgerufen werden. Dies führte aber zu Problemen, weshalb diese Version erneut stark überarbeitet werden musste. Das erste Problem war, dass Views asynchron funktionieren, im Gegensatz zu direkten Abfragen, die synchron sind. Dies hatte zur Folge, dass Benutzer, die bereits angemeldet sind, oft noch nicht über die Views abgefragt werden können. Außerdem ist nicht spezifiziert, ab wann die Daten wirklich persistent sind und so auch über die View ersichtlich. Deshalb wurde versucht, soweit es geht auf Views zu verzichten. Dies war möglich, indem die Struktur der Dokumente verändert wurde und alle Abfragen mittels der Grundoperationen durchgeführt wurden. Nur Abfragen, die die gesamten Dokumente betrafen, mussten weiterhin mittels Views bearbeitet werden. Wie die View in Listing 6.3. Sie gibt alle auf dem Server gespeicherten Sessionen zurück, also alle zur Zeit der Abfrage laufenden Sessionen. Diese Art von Views werden nur mehr für Statistikzwecke benötigt. Da in dieser Anwendung jede Sekunde viele Sessionen gestartet und beendet werden, hat es keinen großen Einfluss auf die Korrektheit der Zahlen, wenn eine gewisse Anzahl von Anmeldungen und Abmeldungen in den Views noch nicht erfasst wurde. Listing 6.3: alle Sessionen 1 2 3 4 function (doc, meta) { emit(doc.sessId, null); } Das zweite Problem war, dass bestimmte Abfragen sich nicht auf eine bestimme Session beziehen, sondern auf einen bestimmten Benutzer. Da Views aber nicht benutzt werden können und über die Grundfunktionen nur der Dokumentkey, also in diesem Fall der Sessionkey, verwendet werden kann, war es nötig, eine zweite Dokumentengruppe zu erstellen. Das führt zwar dazu, dass für viele Operationen zweimal die get-Funktion aufgerufen werden muss, was aber kein Problem ist. Laut der Dokumentation von Couchbase [3] sind die Grundoperationen so sehr optimiert, dass sie keinen Einfluss auf die Performance haben. Diese neue Dokumentengruppe hat als Key die BenutzerID und enthält den dazugehörigen Sessionkey. Wie in Abbildung 12 ersichtlich, enthält das Dokument außerdem Informationen über das verwendete Produkt und die verwendete Plattform. Zunächst wurden hier auch alle Listen, wie zum Beispiel die Liste aller wiedergegebenen Titel abgespeichert. Dies führte aber dazu, dass die Dokumente teilweise sehr groß wurden, weshalb die Listen in eigene Dokumente ausgelagert wurden. Abbildung 12: Von den Objekten dieser Klasse werden die Dokumente gebildet und mit dem dazugehörigen Customerkey als Key abgspeichert. 1.1 Architektur Abbildung 13: Die Architektur des SessionCaches und allen relevanten Klassen. In Abbildung 13 ist die Architektur des Session Caches abgebildet. UserResource ist die Schnittstelle zum Client und enthält alle Operationen, sowie notwendige Überprüfungen. In UserCache findet die Interaktion mit dem Couchbase Server statt. Die Verbindung zum Couchbase Server wird wiederum über den CouchbaseClientManager aufgebaut. Er ist als Singleton implementiert, um sicher zu stellen, dass es von der CouchbaseClient Klasse nur eine Instanz gibt. UserBean enthält alle Information über den eingeloggten Benutzer. SessionBean enthält, wie bereits erwähnt, die Session ID. Im SessionWrapper ist eine Liste enthalten, die alle SessionBeans eines Benutzers speichert. Es muss eine Liste sein, da es in einzelnen Fällen möglich ist, dass ein Benutzer mehrmals zur selben Zeit eingeloggt ist. 1.2 Weitere Caches Es gibt noch drei weitere Caches, sie sind fast identisch wie der Session Cache aufgebaut. Zwei von ihnen sind für Synchronisationsaufgaben zuständig und enthalten meist nicht mehr als zwei bis drei Dokumente. Der dritte Cache speichert für eine gewisse Zeit alle Daten zu Titeln, die aus dem Backend geladen wurden. So wird dessen Datenbank entlastet. Außerdem wurde kurz vor Abschluss dieser Arbeit der UserCache erweitert, damit er auch eine zweite, verkleinerte Version von UserBean bearbeiten kann. Dies wurde nötig, da ein neues Produkt eingeführt wird, wo viele Daten, die im UserBean gespeichert werden, nicht vorhanden sind. Aber abgesehen davon funktioniert die Abarbeitung der Anfragen exakt wie für das UserBean. 2 Die Listen Es werden zwei Listen pro Benutzer angelegt, Alle wiedergegebenen Titel und Die letzten 50 wiedergegebenen Titel pro Produkt. Der Unterschied liegt darin, dass die erste Listealle wiedergegebenen Titel seit Registrierung des Benutzers speichert, unabhängig vom verwendetem Produkt oder verwendeter Plattform. Die zweite Liste ist wie eine Queue aufgebaut. Sind bereits 50 Titel gespeichert wird vor dem Speichern eines neuen Titels der älteste aus der Liste entfernt, so kann sie nie größer als 50 Titel werden. Außerdem wird für jedes erworbene Produkt eine eigene Liste angelegt, so werden zum Beispiel Sport und Kinofilme in verschiedenen Listen erfasst. Zunächst wurden diese Listen im selben Dokument wie das oben erwähnte Sessionbean gespeichert, da dies aber das Dokument stark vergrößert hat, wurde schließlich ein eigenes Dokument für jede Liste angelegt. Als Key muss ebenfalls der Customerkey verwendet werden. So würden aber mehrere Dokumente den selben Key besitzen, was nicht möglich ist. Um das zu umgehen, wurde der Key für jeden Dokumententyp mit einem Prefix versehen, so wie es in der Dokumentation empfohlen wird [3]. So wurde zum Beispiel das Dokument mit dem Sessionbean, mit dem Prefix sess:: versehen und das Dokument mit der Liste aller wiedergegeben Titel mit dem Prefix wl::. Abbildung 14: Die Listen müssen in Wrapperklassen gepackt werden, um Cast-Errors zu umgehen. Zunächst war geplant, die Listen direkt in Couchbase zu speichern, was grundsätzlich auch zulässig wäre. Jedoch führte das direkte Speichern der Listen bei einem get() zu Castproblemen, da die Listen nur als List gespeichert werden und die Information welche Objekte sich in der Liste befinden (was über die Generics definiert wird) geht verloren. So wurde zum Beispiel für die Liste aller wiedergegeben Titel nicht List<WatchlistBean > akzeptiert. Aus diesem Grund mussten die Listen in Wrapperklassen, wie in Abbildung 14 ersichtlich, gepackt werden. Diese Klassen enthalten nur die jeweilige Liste sowie einige Methoden, die die Bearbeitung an die Methoden der Liste weitergeben. 2.1 Architektur In Abbildung 15 ist die Architektur der Liste aller wiedergegebenen Titel abgebildet. Die Funktionsweise der zweiten Liste ist exakt dieselbe. In WatchlistResource ist die REST-Schnittstelle zum Client implementiert, mit allen Operation, die der Client durchführen kann. Außerdem werden hier alle Überprüfungen zur Korrektheit und Zulässigkeit einer Anfrage durchgeführt. In Watchliststore werden die Anfragen bearbeitet und an CbQuery weitergeben. Diese Klasse interagiert direkt mit dem Couchbase Server und enthält die gesamten Queries. Diese sind oft generisch gehalten, damit sie von mehreren Methoden verwendet werden können. Die Verbindung zum Couchbase Server wird wiederum über den CouchbaseClientManager aufgebaut. Der CouchbaseClientManager wird im gesamten Projekt immer wieder verwendet. WatchlistBean wird sowohl in WatchlistStore als auch in CbQuery verwendet. Es wird erst im letzten Moment für die Speicherung in der Datenbank im WatchlistWrapper verpackt. Abbildung 15: Das Klassendiagramm von Watchlist und allen relevanten Klassen. 3 Bookmarking Die Bookmarkingfunktion war vor dem Start dieser Arbeit auf der Clientsite implementiert. Das hatte zur Folge, dass die erstellten Bookmarks nur für die jeweilige Plattform gültig waren. Hat ein Benutzer einen Titel im Webclient unterbrochen und wollte ihn am Smartphone fortsetzen war dies nicht ohne weiteres möglich. Desshalb sollte diese Funktion in den Middlelayer verschoben werden, um sie plattformunabhängig zu machen. Das Objekt enthält den Titel und den Zeitpunkt, an dem die Wiedergabe unterbrochen wurde. Wie bei den Listen der gesehenen Titel werden hier die Objekte in einer Liste gespeichert und anschließend in einer Wrapperklasse verpackt, die dann auf dem Couchbase Server gespeichert wird. Die Struktur des Dokuments sieht dann ungefähr wie in Listing 6.4 abgebildet aus. Wobei assedId die eindeutige ID des Titels ist und time die Abspielzeit, zu der die Wiedergabe unterbrochen wurde. Die Bookmarks werden automatisch erstellt, wenn ein Titel unterbrochen wurden. Wenn der Titel fertig abgespielt wurde, wird er wieder aus der Liste entfernt. Auch hier wird die User ID als Key für die Liste verwendet. Die gesamte Architektur für das Bookmarking ist den vorher erklärten Listen sehr ähnlich, weshalb sie hier nicht noch einmal erklärt wird. Listing 6.4: Beispiel eines Bookmark Dokumentes 1 { "bookmark": [ {"assedId": 135, "time":"24:12"}, {"assedId": 213, "time":"62:00"}, {"assedId": 322, "time":"05:39"} ] 2 3 4 5 6 7 } 4 Check and Set (CAS) Couchbase bietet keine Transaktionen im herkömmlichen Sinne, so wie es relationale Datenbanken tun. Um trotzdem mehrere, von einander abhängige Befehle threadsave zu machen, sind im Framework mehrere so genanne CAS-Operationen implementiert. Sie arbeiten mit den CAS-Objekten aus der Memcached-Library. Damit kann der Entwickler selbst entscheiden wo es zu Konsistenzproblemen kommen kann und diese verhindern. CAS-Operationen erlauben das Updaten nur, wenn sich zwischen dem Lesen und dem Schreiben eines Wertes die dazugehörige, eindeutige ID nicht verändert hat. Diese ID wird CAS-Value genannt. Es wird also nur dem Benutzer mit dem neusten CAS-Value erlaubt, die Datei zu ändern, allen anderen wird eine Fehlermeldung ausgegeben und sie müssen die Operation gegebenenfalls erneut durchführen [3]. Es gibt auch Locks, die Dokumentation empfiehlt diese aber nur in ganz speziellen Fällen zu verwenden, da sie die Performance erheblich beeinträchtigen. Da bei den großen Datenmengen die Wahrscheinlichkeit sehr gering ist, dass zwei Benutzer zur selben Zeit die selben Werte ändern, empfehlen sich meist die CAS-Operationen als gute Alternative [3]. Die CAS-Operation können in zwei Gruppen aufgeteilt werden, get-with-cas und checkand-set. Die erste Gruppe gibt ein Objekt zurück, das den Wert selbst sowie den dazugehörigen CAS-Value enthält. Nach der Bearbeitung des Wertes wird mit einer Operation aus der zweiten Gruppe der neue Wert und der CAS-Value übergeben. Als Rückgabewert wird eine sogenannte CASResponse geliefert. Darin enthalten ist eine der Konstanten aus Tabelle 6.2, dadurch kann ermittelt werden, ob die Operation erfolgreich war oder nicht.[3]. Ausgehend von der CASResponse kann der Entwickler entscheiden, wie reagiert werden soll. In dieser Anwendung wurde bei negativer Rückmeldung die Operation wiederholt. Außer bei einem NOT FOUND, dann wird eine einfache add() Operation ausgeführt, um den Wert einzufügen. Diese Art von Operationen werden in dieser Arbeit vor allem für den Session Cache benötigt, da hier bei jeder Aktualisierung das UserBean sowie das SessionBean verändert EXISTS NOT FOUND OBSERVE ERROR IN ARGS OBSERVE MODIFIED OBSERVE TIMEOUT OK Der Wert ist in der Datenbank vorhanden, aber mit einem anderen CAS-Value als erwartet Der Wert ist in der Datenbank nicht vorhanden Es gab einen Fehler beim Festlegen der Argumente Der Wert wurde verändert Es kam zu einem Timeout Die Operation war erfolgreich Tabelle 6.2: Alle möglichen Werte von CASResponse [3] wird. Um Inkonsistenzen zu verhindern, muss die Änderung für beide erfolgreich sein, oder gar nicht erfolgen. Aus diesem Grund müssen mit Hilfe von CAS-Befehlen Transaktionen simuliert werden. 5 REST-Schnittstellen Für den Zugriff auf die Sessionverwaltung sowie auf die Listen und das Bookmarking durch den Client, wird eine REST-Schnittstelle implementiert. Zur Realisierung werden die Annotations aus dem javax Package verwendet. mit @Path() wird der Pfad zu den Klassen sowie zu bestimmten Methoden festgelegt. Dieser Pfad wird dann in den HTTP-Befehlen vom Client benutzt, um eine bestimmte Methode aufzurufen. Mit @PUT, @POST und @DELETE wird festgelegt, um welche Art von Methode es sich handelt. Außerdem muss für jede Methode eine Wrappermethode mit @GET und eigenem Pfad implementiert werden, da der Webclient nur mittels GET kommunizieren kann. Zusätzlich werden im Methodenkopf mit @QueryParam() die Parameter festgelegt, die mit dem HTTP-Befehl übergeben werden. Vor jeder Methode muss auch definiert werden, wie der Rückgabewert verpackt wird. Das geschieht mit @Produces(). Darin kann zum Beispiel mit application/json mitgeteilt werden, dass der Rückgabewert in einem Json-Dokument verpackt ist. Innerhalb der Methoden findet eine Reihe von Überprüfungen statt, bevor die Anfrage abgearbeitet wird. Es wird zuerst überprüft ob alle übergebenen Parameter in der richtigen Form sind und vom richtigen Datentyp. Außerdem wird kontrolliert, ob der Benutzer berechtigt ist, eine solche Anfrage zu tätigen. Fällt eine dieser beiden Überprüfungen negativ aus, wird sofort dem Client geantwortet und diesem der entsprechende Fehlercode geschickt. Fällt die Überprüfung positiv aus, wird kontrolliert von welcher Plattform aus die Anfrage geschickt wurde und welche Version der Client hat. Das ist deshalb wichtig da für verschiedene Plattformen und Versionen sich das Format des Dokumentes ändert, das zurück geschickt wird. So erwarten ältere Versionen noch ein XML-Dokument, neuere Versionen arbeiten hingegen mit JSON. Sind alle Überprüfungen getätigt, wird der Befehl abgearbeitet, das entsprechende Dokument erstellt und an den Client zurückgeschickt. Evaluierung Nach Abschluss der Implementierungsarbeit wurden verschiedene Tests durchgeführt, damit entschieden werden kann, ob die neue Implementierung auch in der Produktion zum Einsatz kommen kann. Dazu wurden Integrationstests und Performancetests durchgeführt. Außerdem wurde eine stark vereinfachte Version mittels MongoDB [6] implementiert, um die Unterschiede zu diesem Datenbanksystem zu erkennen. 1 Integrationtests Mittels Maven [2] wurde eine komplette Testumgebung entwickelt, die alle möglichen Szenarien simuliert und zwar für den gesamten Middlelayer, beginnend von der Anfrage des Clients bis hin zu Anfragen an das Backend. Da das Backend von einem anderen Unternehmen implementiert wurde, wurde eine Mockupversion des Backends entwickelt, sowie eine dazugehörige Datenbank. Dieses Mockup wurde rein für Testzwecke implementiert. Die Anfragen des Clients werden direkt von der Testumgebung simuliert. Es handelt sich hier um White-Box-Tests. Das bedeutet, dass mit Blick auf den Code jede Verzweigung getestet wird und jede mögliche Fehlermeldung generiert wird. Dadurch kann sicher gestellt werden, dass es zu keinen unerwarteten Verhalten durch die Anwendung kommt. Die Integrationtests waren bereits fertig entwickelt. Sie mussten aber an die neue Implementierung angepasst werden. Außerdem mussten sie erweitert werden, um die neuen Funktionen ab zu decken. 2 Performance Während der Entwicklungs- und Testzeit dieser Anwendung lief Couchbase Server auf einem Cluster mit zwei Servern. Diese hatten jeweils 8 GB RAM und eine dualcoreProzessor. Anfangs wurde nur mit einem Singlecore-Prozessor gearbeitet, was sehr schnell zu Überlastungen führte. Das war aber nicht weiter verwunderlich, da von Couchbase mindestens ein Dualcore-Prozessor empfohlen wird. 41 Während der Entwicklung, im laufe des Praktikums, war es leider nicht möglich selber entsprechende Performancetest durch zu führen und Couchbase direkt mit anderen System zu vergleichen. Der Grund dafür ist, dass nicht die erforderliche Infrastruktur zur Verfügung stand. Es gab zwar einen Server auf dem Couchbase während der Entwicklung lief, jedoch war er gerade ausreichend für einfache Unit- und Integrationtests. Die folgenden Benchmarks zeigen jedoch, dass Couchbase, unter normalen Umständen, eine erhebliche Performancesteigerung bringt. Auch wenn sich später zeigen sollte, dass sich die Performance durch diese Arbeit nicht erheblich verbessert hat, ändert dass nichts daran, dass die Neuerungen nötig waren. Der Grund dafür ist, dass das alte System durch die immer steigenden Benutzerzahlen, an seine Belastungsgrenzen gestoßen ist und verbessert werden musste. 2.1 Benchmarks Das unabhängige Unternehmen Thumbtack Technlologies hat einen Benchmarktest veröffentlicht, wo MongoDB, Couchbase und Cassandra miteinander verglichen wurden [14]. Dabei wurden die NoSQL Datenbanksysteme auf Operationen pro Sekunde, Latenz und Skalierung geprüft und verglichen. Alle drei Testfälle wurden in zwei Ausführungen durchgeführt. Einmal mit 50 % Schreibe- und 50 % Lesebefehlen und einmal mit 5 % Schreibe- und 95 % Lesebefehlen. Das wurde deshalb gemacht, da viele Anwendungen, die NoSQL als Datenbank benutzen, vor allem hohe Leseraten haben. Außerdem wurden die Tests jeweils mit Clustern von 4, 6 und 8 Servern durchgeführt. Operationen pro Sekunde Bei dem ersten Test, wo nur auf die Operationen pro Sekunde geachtet wird, liegt Couchbase weit vorne, was aber absehbar war, da Couchbase vor allem mit ihren Grundoperationen wirbt, die hoch optimiert sind. Es wird sogar empfohlen diese Grundoperationen viel einzusetzen, da sie nahezu keine Auswirkungen auf die Performance haben. Wie in Abbildung 16 zu sehen ist, schafft Couchbase in der Sekunde fast 16-mal mehr Operationen als die beiden anderen Datenbanksysteme. In dem 5% read/95% write Test ist MongoDB etwas besser als im 50% read/50% write Test, allerdings reicht es nie an die Anzahl der Operationen von Couchbase heran. Latency Für die Resultate in Abbildung 17 wurde der Durchschnitt jener Werte heran gezogen, die gemessen wurden, bis kurz bevor die Verzögerung stark ansteigt. Wie im Bericht Abbildung 16: Die Operationen pro Sekunde für 4, 6 und 8 Knoten.[14] festgestellt wird, ist das eine rein subjektive Entscheidung. Sie macht jedoch Sinn, da dies die Grenze ist, an der die Datenbank noch in vernünftiger Zeit Ergebnisse liefert. Die Unterschiede zwischen den Datenbanken sind hier nicht mehr so eindeutig. Vor allem Couchbase und MongoDB haben ähnliche Werte. Sie sind bei den 5% read/95% Test um einiges besser als bei dem 50% read/50% write Test. Bei Cassandra ist es genau umgekehrt, was aber nicht weiter verwunderlich ist, da Cassandra stark optimierte Schreiboperationen hat. Abbildung 17: Die Durchschnittliche Verzögerungszeit für die verschiedenen Datenbanksysteme [14] Skalability Im Test zu der Skalierung, wurde beobachtet wie gut die jeweiligen Datenbanksysteme skalieren, wenn die Cluster von 5 auf 6 und 6 auf 8 Knoten erweitert werden. In der Tabelle 7.3 sind die Ergebnisse aufgelistet. Bei dem 5% read/95% Test skalieren Couchbase und MongoDB annähernd linear, während Couchbase die besten Werte liefert. Cassandra skaliert am schlechtesten, jedoch muss gesagt werden, dass Cassandra nicht auf kleine Cluster mit nur 4 Knoten ausgelegt ist. Beim 50% read/50% write Test liefert MongoDB die besten Ergebnisse, mit einer Skalierung von 72,16 %. Couchbase und Cassandra skalieren beide ungefähr halb linear. 5/95 Test Cassandra 2.0.9 Couchbase 2.5.1 MongoDB 2.6.4 50/50 Test Cassandra 2.0.9 Couchbase 2.5.1 MongoDB 2.6.4 Scaling 4 ->6 21.07% 42.16% 48.73% Scaling 4 ->6 25.10% 26.63% 36.44% Scaling 6 ->8 64.38% 89.57% 73.64% Scaling 6 ->8 66.48% 55.74% 71.44% Average 53.26% 86.95% 85.55% Average 58.35% 54.50% 72.16% Tabelle 7.3: Die Skalierung in Prozen von 4 bis 8 Knoten [14] In diesen Tests ist zu erkennen, dass Couchbase vor allem eine sehr gute Performance hat, wenn nur die Operationen pro Sekunde betrachtet werden. Außerdem ist es vor allem für Leseoperationen gut optimiert. Aber auch in den anderen Tests liegt Couchbase meist im guten Mittelfeld. Das macht Couchbase für die meisten Fälle zu einer guten Option. 3 Couchbase vs. MongoDB Für diesen Vergleich wurde die Anwendung teilweise erneut mit MongoDB anstelle von von Couchbase Implementiert. Außerdem wurde der technische Bericht The NoSQL ” Technical Comparison Report“ [7] von Altros als Quelle herangezogen. Darin werden Couchbase, Cassandra und MongoDB verglichen, in dieser Arbeit wird aber auf dem Vergleich zu Cassandra verzichtet. Installation und Konfiguration Die Installation von Couchbase ist sehr einfach, es muss nur das Installationsfile ausgeführt werden und man hat bereits einen einfachen, funktionsfähigen Server. Die Konfiguration ist einfach und intuitiv, da alles über die graphische Web-Console erledigt werden kann. Bei MongoDB ist es bereits schwieriger, da es nach dem Master-Slave-Prinzip funktioniert und das zuerst festgelegt werden muss. Außerdem bietet MongoDB nur ein textbasiertes Consoleninterface, was es für Anfänger schwieriger macht, sich einzuarbeiten. Architektur MongoDB unterstützt Master-Slave-Replication, das bedeutet, nur ein bestimmter Masterknoten akzeptiert Schreibbefehle und gibt sie dann an seine Slaveknoten weiter. Außerdem ist es möglich, so genannte sharded Cluster zu erstellen, das sind Zusammenschlüsse von mehreren Replicasets. Dann ist es aber nötig, einen Konfigurationsserver zu erstellen, der wichtige Metadaten enthält, sowie die Weitergabe von Daten zwischen den Replicasets managt. Couchbase hat auch hier ein einfacheres System. Es ist als Peer-to-Peer-Netz aufgebaut und alle Knoten sind gleichwertig. Jeder Koten enthält einen Clustermanager und einen Datamanger. Der Clustermanager ist für alle Funktionen zuständig, die eine Kommunikation zwischen den Knoten erfordern. Das ist zum Beispiel die Replikation der Daten oder das Rebalancing, wenn ein Knoten down geht. Der Datamanager ist für Zugriff und Speicherung der Daten zuständig. So entscheidet er zum Beispiel, wenn Daten aus dem Hauptspeicher auf die Platte gschrieben werden. Konsistenz In Couchbase wird Konsistenz zwar garantiert, aber durch die asynchronen Operationen ist nicht festlegbar, ab wann das System konsistent ist. Das kann aber durch die so genannten CAS-Befehle überprüft und so können Probleme vermieden werden. In MongoDB werden standardmäßig alle Schreibe- und Lese Befehle über den Masterknoten abgewickelt, so kann eine volle Konsistenz garantiert werden. Um die Performance zu erhöhen, können Lesezugriffe auch über andere Knoten erlaubt werden. Dadurch ist nicht mehr sofortige Konsistenz garantiert, was zu Problemen führen kann, da es keine Befehle zur Überprüfung, so wie in Couchbase gibt. Entwicklung MongoDB bietet eine sehr gute Dokumentation. Außerdem gibt es eine wachsende Community, die in vielen Blogs und Foren Hilfen bietet. Administrationsaufgaben müssen über die Console erledigt werden, was vor allen am Anfang mehr Einarbeitung benötigt. Die Libraries für die verschiedenen Sprachen bieten eine gute Menge an Operationen, die einfach und intuitiv angewendet werden können. Ebenso bietet Couchbase eine sehr umfangreiche Dokumentation mit Tutorials, Webinars und Whitepapers. Auch gibt es eine sehr aktive Community, die viele Hilfen bietet. Die grafische Web-Console bietet eine leichte Administration, die auch von Anfängern schnell bedienbar ist. Die Libraries sind sehr umfangreich. Und die Views können mittels Javascript direkt in der Web-Console geschrieben und getestet werden. Außerdem wurde mit der Version 3.0 die Couchbase Querie Language (N1QL) eingeführt, die das Durchsuchen der Daten erleichtert. Zusammenfassung und Ausblick In dieser Arbeit wurden die Vorteile von NoSQL Datenbanken beschrieben, vor allem für Bigdata Anwendungen. Im Speziellen wurde die Datenbank Couchbase betrachtet, es wurde aber auch im Allgemeinen auf nicht relationale Datenbanken und die Unterschiede zu relationalen Datenbanken eingegangen. Außerdem wurde das Sessionmanagement eines Streamingdienstes erneuert. Dazu wurden die alten Cachingsysteme sowie Teile der relationalen Datenbank entfernt und durch Couchbase ersetzt. Das war nötig, um den steigenden Benutzerzahlen gerecht zu werden und die vom Benutzer geforderte Geschwindigkeit und Leistung garantieren zu können. Wie in der Evaluierung ersichtlich ist, war die Auswahl von Couchbase als Datenbank die richtige Entscheidung. Es ist ein sehr performantes System und auch sehr flexibel, was es auf alle erforderlichen Situationen anpassen lässt. Das im Praktikum erstellte Programm wurde vom Unternehmen sehr positiv bewertet und es wird dem Auftraggeber der Software vorgeschlagen, die Änderungen in der Produktion anzuwenden. Die letzte Entscheidung liegt natürlich beim Auftraggeber, da die Umstellung mit weiteren Kosten einhergeht. Es müssen zum Beispiel neue Server angekauft und angepasst werden. Wir sind aber sehr optimistisch, dass der Auftraggeber unseren Empfehlungen folgen wird. 47 Literaturverzeichnis [1] Introduction of cache memory. https://www.cs.umd.edu/class/fall2001/cmsc411/ proj01/cache/cache.pdf, 2001. Faculty of Computer Science, University of Maryland, accessed 18-11-2014. [2] Apache maven project. http://web.archive.org/web/20141218084045/http://maven.apache.org/, 2014. [Online; accessed 18-December-2014]. [3] Couchbase. http://web.archive.org/web/20141127092720/http://www.couchbase.com/, 2014. [Online; accessed 27-November-2014]. [4] Couchdb. http://web.archive.org/web/20141216122043/http://couchdb.apache.org/, 2014. [Online; accessed 16-December-2014]. [5] Memcached. http://web.archive.org/web/20141127102540/http://memcached.org/, 2014. [Online; accessed 27-November-2014]. [6] Mongodb. http://web.archive.org/web/20141218083651/http://www.mongodb.org/, 2014. [Online; accessed 18-December-2014]. [7] The nosql technical comparison report, tech. report, Altros, 2014. [8] D. Abadi, P. Boncz, S. Harizopoulos, S. Idreos, and S. Madden, The design and implementation of modern column-oriented database systems, Foundations and Trends in Databases, 5 (2013), pp. 197–280. [9] R. Angles and C. Gutierrez, Survey of graph database models, ACM Comput. Surv., 40 (2008), pp. 1:1–1:39. [10] G. Antoniou and F. v. Harmelen, A Semantic Web Primer, 2Nd Edition (Cooperative Information Systems), The MIT Press, 2 ed., 2008. [11] L. Ashdown and T. Kyte, Oracle Database Concepts 11g Release 2 (11.2), Oracle. [12] M. Brown, Developing with Couchbase Server, O’Reilly Media, 2013. [13] R. Fielding, J. Gettys, J. Mogul, H. Frystyk, L. Masinter, P. Leach, and T. Berners-Lee, Hypertext transfer protocol – http/1.1 (rfc 2616). Request For Comments, 1999. available at http://www.ietf.org/rfc/rfc2616.txt, accessed 7 July 2006. 49 [14] A. Gusev and S. Pozdnyakov, Nosql performance when scaling by ram, tech. report, Thumbtack Technology, 2014. [15] S. Idreos, F. Groffen, N. Nes, S. Manegold, S. Mullender, and M. Kersten, Monetdb: Two decades of research in column-oriented database architectures, IEEE Data Eng. Bull, (2012). [16] A. Rodriguez, RESTful Web services: The basics, 2008. [17] P. Sadalage and M. Fowler, NoSQL Distilled: A Brief Guide to the Emerging World of Polyglot Persistence, Pearson Education, 2012. [18] F. Stajano, A gentle introduction to relational and object oriented databases, Tech. Report ORL-TR-98-2, The olivetti and oracle research laboratory, 1998. [19] Terracotta, Ehcache 2.6.x Documentation. [20] S. Tiwari, Professional NoSQL, Programmmer to programmer, Wiley, 2011.