Elasticsearch – Ein praktischer Einstieg

Änderungen in Elasticsearch 2.0

Die Arbeit an einem Buch zu einem lebendigen Open-Source-Projekt wie Elasticsearch kann stellenweise frustrierend für den Autor sein – kaum ist ein Kapitel abgeschlossen ist es auch schon veraltet, weil Features verbessert oder neue hinzugekommen sind. Das Elasticsearch-Buch ist für Version 1.6 geschrieben, noch vor Veröffentlichung ist jedoch Elasticsearch 2.0 erschienen. Dieser Artikel geht auf einige das Buch betreffende Änderungen in Elasticsearch 2.0 ein und zeigt, dass der Unterschied gar nicht so groß ist wie es sich durch den Versionssprung eventuell anhört.

Filter und Queries

Beim Zugriff auf Elasticsearch kann die Ergebnismenge entweder über Queries oder über Filter eingeschränkt werden. Die beiden größten Unterschiede dabei sind, dass Queries eine zusätzliche Relevanzberechnung durchführen und Filter gecacht werden können. In Elasticsearch-Versionen vor 2.0 wurden diese beiden Aspekte über unterschiedliche Objekte formuliert. So gab es zur direkten Abfrage nach Termen im Index sowohl eine Term-Query als auch einen Term-Filter.

Mit Elasticsearch 2.0 wurde diese Unterscheidung aufgehoben, intern werden jetzt für Filter und Queries dieselben Objekte verwendet. Dadurch sind unterschiedliche Optimierungen möglich, beispielsweise das automatische Caching von Filtern.

Der deutlichste Unterschied, der sich für den Benutzer ergibt, ist die Anwendung von Filtern. In älteren Elasticsearch-Versionen kommt dazu meist die Filtered-Query zum Einsatz, die Query und Filter aktzeptiert. Im Buch wird als Beispiel die Suche in Konferenzdaten verwendet. Um Konferenzen zu suchen, die den Begriff elasticsearch im Titel enthalten und das Schlagwort Java gesetzt haben kann dann die folgende Abfrage verwendet werden.

{
   "query": {
      "filtered": {
         "query": {
            "match": {
               "title": "elasticsearch"
            }
         },
         "filter": {
            "term": {
               "tags": "Java"
            }
         }
      }
   }
}

Mit Elasticsearch 2.0 ist die Filtered-Query als deprecated markiert und wird also in Zukunft entfernt. Stattdessen akzeptiert die Bool-Query jetzt zusätzliche Filter. Mit Elasticsearch 2.0 würde die Abfrage also folgendermaßen aussehen.

{
   "query": {
      "bool": {
         "must": {
            "match": {
               "title": "elasticsearch"
            }
         },
         "filter": {
            "term": {
               "tags": "Java"
            }
         }
      }
   }
}

Weitere Details zu den Vorteilen der Zusammenführung von Filtern und Queries sind auch in einem Blogpost von Adrien Grand beschrieben.

Netzwerkkonfiguration und Kommunikation im Cluster

Das Kapitel 6 im Buch widmet sich ausführlich der Verteilung der Daten in Elasticsearch und der Kommunikation im Cluster. Dabei ist auch der Multicast-Mechanismus ein Thema, der den einfachen Start mit Elasticsearch erlaubt, da sich neue Knoten ohne weitere Kommunikation mit bestehenden Elasticsearch-Instanzen im Netzwerk verbinden.

Dieses Verhalten macht einen einfachen Start möglich, hat jedoch auch gewaltige Nachteile, vor allem wenn es zu ungewollten Verbindungen mit einem Produktivcluster kommt. Deshalb war schon immer empfohlen statt des Multicast-Mechanismus für Produktionsumgebungen auf Unicast umzusteigen.

Mit Elasticsearch 2.0 ist Unicast standardmäßig aktiv und der Multicast-Mechanismus nur noch als Plugin verfügbar. Dadurch ist nicht mehr möglich, dass sich Instanzen ungewollt miteinander verbinden, die Knoten müssen jetzt explizit konfiguriert werden. Damit der Start jedoch auch weiterhin leicht fällt ist die Konfiguration so ausgelegt, dass sich Elasticsearch standardmäßig mit Instanzen auf der selben Maschine verbindet. Damit bleibt das bisherige Gefühl der magischen Clusterbildung erhalten.

Eine weitere wichtige Änderung ist, dass Elasticsearch ohne weitere Konfiguration nur noch auf Anfragen von der selben Maschine reagiert. Dadurch ist es weniger wahrscheinlich, dass ungewollt Zugriff auf Elasticsearch-Instanzen ermöglicht wird.

Die Änderungen bezüglich der Netzwerkeinstellungen sind auch in einem Blogpost von Clinton Gormley zusammengefasst.

Zusätzlich zu den netzwerkspezifischen Änderungen wurde die Verteilung des Cluster-Zustands deutlich verbessert. Bei Änderungen wird jetzt nicht mehr der komplette Status übertragen sondern nur noch der Unterschied.

Mapping

Im Buch wird im Kapitel zu Datenmodellierung auf ein Problem des Mappings eingegangen. In Elasticsearch-Versionen vor 2.0 können gleichnamige Felder in unterschiedlichen Typen eines Index unterschiedlich konfiguriert werden. Solche Felder werden jedoch im selben Lucene-Index abgelegt, der dann die Daten auf unterschiedliche Weise im selben Feld verwaltet. Dadurch können sich mehrere Probleme ergeben, vor allem wenn über mehrere Typen oder Indizes gesucht wird. In Elasticsearch 2.0 ist es nicht mehr erlaubt, dass gleichnamige Felder inerhalb der Typen eines Index unterschiedlich konfiguriert werden.

Eine kleine Änderung ergab sich bezüglich der Konfiguration der Analyzer für ein Feld. In Versionen vor 2.0 konnte der Analyzer über die Attribute analyzer, search_analyzer und index_analyzer konfiguriert werden. In Elasticsearch 2.0 ist index_analyzer entfernt worden, die Konfiguration erfolgt jetzt nur noch über analyzer.

Details zu diesen und weiteren Änderungen am Mapping finden sich in einem Blogpost von Clinton Gormley.

Performance und Resiliency

Das Kapitel zur Indizierung enthält einige Details zum Translog, das Dokumente vorhält, die noch nicht persistent im Index gespeichert sind. In Elasticsearch-Versionen vor 2.0 wurde dieses innerhalb eines konfigurierbaren Zeitraums, standardmäßig alle fünf Sekunden, auf die Festplatte persistiert. Mit Elasticsearch 2.0 wird jeder Schreibvorgang direkt auf die Festplatte gesynct, um möglichen Datenverlust zu vermeiden.

Im Zusammenhang mit den Aggregationen wird auf Doc-Values eingegangen, die den Speicherverbrauch deutlich verringern können. Mit Elasticsearch 2.0 sind Doc-Values standardmäßig aktiv.

Wie schon im Buch beschrieben wurde die River-Funktionalität in Elasticsearch 2.0 entfernt.

Neue Features

Neben den beschriebenen Änderungen sind noch weitere Features hinzugekommen, die es nicht mehr ins Buch geschafft haben. Hervorzuheben sind dabei die Pipeline-Aggregationen, die genutzt werden können, um auf den Ergebnissen von Aggregationen neue Werte zu berechnen. Colin Goodheart-Smithe hat auf dem elastic-Blog eine Einführung zu dem Thema veröffentlicht und Zachary Tong zeigt in einem zweiteiligen Artikel einen Anwendungsfall am Beispiel der Moving-Averages-Funktion.

Als Stored markierte Felder wie beispielsweise das _source-Feld können in Elasticsearch auf konfigurierbare Weise komprimiert werden. Adrien Grand hat die Änderungen in einem interessanten Blogpost zusammengefasst.

Fazit

Die Änderungen mit Elasticsearch 2.0 sind an vielen Stellen interner Natur und der Benutzer merkt keinen großen Unterschied. Features wie Multicast sind entfernt worden, das Mapping wurde bezüglich der Ablage gleicher Felder innerhalb der Typen eines Index angepasst und Filter und Queries wurden vereinheitlicht. Der deutlichste Unterschied ist sicher, dass die häufig eingesetzte Filtered-Query jetzt stattdessen als Bool-Query formuliert werden sollte.

Es lässt sich nich vermeiden, dass nach und nach einzelne Teile des Buchs nicht mehr aktuell sein werden. Ich freue mich aber, dass das Buch mit kleinen Ausnahmen auch noch für Elasticsearch 2.0 gültig ist.

Zur Unterstützung der Migration älterer Elasticsearch-Versionen auf 2.0 stellt elastic ein Migrations-Plugin zur Verfügung.