Elasticsearch in der Produktion - Best Practices für die Bereitstellung

Elasticsearch ist eine hochoptimierte Suchmaschine für die moderne Datenanalyse.

Elasticsearch ist eine erstaunliche Such- und Analyse-Engine in Echtzeit. Es basiert auf Apache Lucene. Es ist verteilt, RESTful, einfach zu bedienen und hochverfügbar. Zu den Anwendungsfällen von Elasticsearch gehören die Suche, die Transaktionsüberwachung und Fehlererkennung, die Inhaltserkennung, die Protokollanalyse, die Fuzzy-Suche, die Aggregation von Ereignisdaten und die Datenvisualisierung. Elasticsearch und der Rest des Elastic Stacks haben sich als äußerst vielseitig erwiesen. Wie Sie oben sehen können, gibt es mehrere Möglichkeiten, Elasticsearch in das zu integrieren, was Ihr Produkt heute liefert, und ihm zusätzliche Einblicke zu verleihen.

Wir setzen es bei Botmetric stark für Such- und Analysezwecke ein, indizieren täglich etwa eine Milliarde Dokumente und verwenden sehr komplexe Aggregationen für die Datenvisualisierung in Echtzeit.

Das heißt, Bootstrapping einer Anwendung im Vergleich zu deren Ausführung in der Produktion und Wartung ist völlig anders. Dieser Artikel deckt viele dieser Faktoren aus der Praxis ab und stellt die grundlegenden allgemeinen Elemente dar, die Sie bei der Ausführung von Elasticsearch in der Produktion berücksichtigen sollten.

Erinnerung:

Elasticsearch und Lucene sind in Java geschrieben, was bedeutet, dass Sie auf den Heapspace und die JVM-Statistiken achten müssen. Je mehr Heap für Elasticsearch verfügbar ist, desto mehr Speicher kann für Filter und anderes Caching verwendet werden, um die Abfrageleistung zu verbessern. Beachten Sie jedoch, dass zu viel Speicherplatz zu langen Speicherbereinigungspausen führen kann. Stellen Sie Xmx nicht über dem Grenzwert ein, den die JVM für Zeiger auf komprimierte Objekte verwendet (komprimierte Hoppla!). Der genaue Grenzwert variiert, liegt jedoch nahe 32 GB.

Ein häufiges Problem ist die Konfiguration eines zu großen Heapspeichers. Sie haben eine 64-GB-Maschine - und Sie möchten Elasticsearch alle 64 GB Arbeitsspeicher zur Verfügung stellen. Mehr ist besser! Haufen ist definitiv wichtig für Elasticsearch. Es wird von vielen speicherinternen Datenstrukturen verwendet, um einen schnellen Betrieb zu gewährleisten. Trotzdem gibt es einen anderen großen Speicherbenutzer, der nicht auf dem Haufen ist: den OS-Dateicache.

Lucene wurde entwickelt, um das zugrunde liegende Betriebssystem für das Zwischenspeichern von Datenstrukturen im Speicher zu nutzen. Lucene-Segmente werden in einzelnen Dateien gespeichert. Da Segmente unveränderlich sind, ändern sich diese Dateien nie. Dies macht sie sehr cachefreundlich, und das zugrunde liegende Betriebssystem sorgt dafür, dass heiße Segmente für einen schnelleren Zugriff im Arbeitsspeicher gespeichert bleiben. Diese Segmente enthalten sowohl den invertierten Index (für die Volltextsuche) als auch die Dokumentwerte (für Aggregationen). Die Leistung von Lucene beruht auf dieser Interaktion mit dem Betriebssystem. Wenn Sie jedoch den gesamten verfügbaren Speicher für den Elasticsearch-Heap freigeben, bleibt für den Dateicache des Betriebssystems nichts übrig. Dies kann die Leistung erheblich beeinträchtigen. Standardmäßig wird empfohlen, 50% des verfügbaren Speichers für den Elasticsearch-Heap freizugeben, während die anderen 50% frei bleiben. Es wird nicht ungenutzt bleiben. Lucene konsumiert gerne alles, was für den Dateicache übrig bleibt. Der Elasticsearch-Heap kann folgendermaßen konfiguriert werden:

export ES_HEAP_SIZE = 10g

oder

ES_JAVA_OPTS = "- Xms10g -Xmx10g" ./bin/elasticsearch

ZENTRALPROZESSOR:

Elasticsearch unterstützt Aggregationen und gefilterte Abfragen. Das Ausführen komplexer gefilterter Abfragen, intensiver Indizierung, Perkolation und Abfragen gegen Indizes erfordert viel CPU. Daher ist es wichtig, die richtige zu finden. Man muss die CPU-Spezifikationen verstehen und wissen, wie sie sich mit Java verhalten, wenn die Abfragen unter JVM ausgeführt werden.

Jeder Pool führt eine Reihe von Threads aus, die konfiguriert werden können und über eine Warteschlange verfügen. Es wird nicht empfohlen, dies zu ändern, es sei denn, Sie haben ganz bestimmte Anforderungen, da Elasticsearch die Zuordnung der Kerne dynamisch durchführt.

Thread-Pool-Typen:

Elasticsearch verfügt über 3 Arten von Thread-Pools.

  1. Zwischengespeichert: Der zwischengespeicherte Thread-Pool ist ein unbegrenzter Thread-Pool, der einen Thread erzeugt, wenn ausstehende Anforderungen vorliegen. Dieser Thread-Pool wird verwendet, um zu verhindern, dass an diesen Pool gesendete Anforderungen blockiert oder abgelehnt werden. Nicht verwendete Threads in diesem Thread-Pool werden beendet, nachdem ein Keep Alive abgelaufen ist (standardmäßig fünf Minuten). Der zwischengespeicherte Threadpool ist für den generischen Threadpool reserviert.
  2. Behoben: Der feste Thread-Pool enthält eine feste Größe von Threads, um die Anforderungen mit einer Warteschlange (optional begrenzt) für ausstehende Anforderungen zu behandeln, für die keine Threads zur Bearbeitung vorhanden sind. Der Parameter size steuert die Anzahl der Threads und gibt standardmäßig die Anzahl der Kerne mal 5 an.
  3. Skalierung: Der Skalierungsthreadpool enthält eine dynamische Anzahl von Threads. Diese Zahl ist proportional zur Arbeitslast und variiert zwischen 1 und dem Wert des Parameters size.

Elasticsearch unterteilt die CPU-Auslastung in Thread-Pools verschiedener Typen:

  • generisch: Für Standardvorgänge wie Discovery und Threadpool wird der Typ zwischengespeichert.
  • index: für Index- / Löschvorgänge. Thread-Pool-Typ ist behoben.
  • Suche: für Zähl- / Suchvorgänge. Thread-Pool-Typ ist behoben.
  • get: für get Operationen. Thread-Pool-Typ ist behoben.
  • Bulk: Für Bulk-Operationen wie die Bulk-Indizierung. Thread-Pool-Typ ist behoben. Die beste Konfiguration von Massendokumenten hängt von der Clusterkonfiguration ab. Dies kann durch Ausprobieren mehrerer Werte ermittelt werden.
  • Perkolation: für die Perkolation. Thread-Pool-Typ ist behoben.
  • Aktualisieren: Für Aktualisierungsvorgänge. Thread-Pool-Typ wird skaliert.

Das Ändern eines bestimmten Thread-Pools kann durch Festlegen der typspezifischen Parameter erfolgen.

Weitere Informationen finden Sie unter https://www.elastic.co/guide/en/elasticsearch/reference/2.2/modules-threadpool.html#types

Scherbengröße:

Der Shard ist die Einheit, in der Elasticsearch Daten innerhalb des Clusters verteilt. Die Geschwindigkeit, mit der sich Elasticsearch beim Neuausgleichen von Daten bewegen kann, z. hängt nach einem Fehler von der Größe und Anzahl der Shards sowie der Netzwerk- und Festplattenleistung ab.

In Elasticsearch wird jede Abfrage in einem einzelnen Thread pro Shard ausgeführt. Es können jedoch mehrere Shards gleichzeitig verarbeitet werden, ebenso wie mehrere Abfragen und Aggregationen für denselben Shard.

Dies bedeutet, dass die minimale Abfragelatenz, wenn kein Caching erforderlich ist, von den Daten, dem Abfragetyp und der Größe des Shards abhängt. Durch das Abfragen vieler kleiner Shards wird die Verarbeitung pro Shard beschleunigt. Da jedoch viel mehr Aufgaben in die Warteschlange gestellt und nacheinander verarbeitet werden müssen, ist dies nicht unbedingt schneller als das Abfragen einer kleineren Anzahl größerer Shards. Viele kleine Shards können auch den Abfragedurchsatz verringern, wenn mehrere Abfragen gleichzeitig ausgeführt werden.

Jeder Shard verfügt über Daten, die im Speicher aufbewahrt werden müssen, und belegt Heapspeicher. Dies schließt Datenstrukturen ein, die Informationen auf Shard-Ebene und auch auf Segmentebene enthalten, um zu definieren, wo sich Daten auf der Festplatte befinden. Die Größe dieser Datenstrukturen ist nicht festgelegt und variiert je nach Anwendungsfall. Ein wichtiges Merkmal der segmentbezogenen Gemeinkosten ist jedoch, dass sie nicht genau proportional zur Größe des Segments sind. Dies bedeutet, dass größere Segmente im Vergleich zu kleineren Segmenten weniger Overhead pro Datenvolumen haben. Der Unterschied kann erheblich sein. Die Auswahl der richtigen Anzahl von Shards ist schwierig, da Sie nie wissen, wie viele Dokumente Sie erhalten, bevor Sie beginnen. Viele Scherben zu haben, kann für einen Cluster sowohl gut als auch schrecklich sein. Die Verwaltung von Indizes und Shards kann den Masterknoten überlasten, was zu einem merkwürdigen und unangenehmen Verhalten führen kann. Weisen Sie Ihren Masterknoten genügend Ressourcen zu, um mit der Clustergröße fertig zu werden.

Das Schlimme ist, dass die Anzahl der Shards unveränderlich ist und beim Erstellen des Index festgelegt wird. Sobald ein Index erstellt wurde, können Sie die Anzahl der Shards nur ändern, indem Sie Ihre Indizes löschen, neu erstellen und neu indizieren.

Replikation

Elasticsearch unterstützt die Replikation. Daten werden zwischen den Datenknoten repliziert, sodass ein Knotenverlust nicht zu Datenverlust führen würde. Standardmäßig ist der Replikationsfaktor 1, er kann jedoch abhängig von Ihren Produktanforderungen erhöht werden. Je mehr Replikate vorhanden sind, desto katastrophenresistenter sind Ihre Daten. Ein weiterer Vorteil von mehr Replikaten besteht darin, dass jeder Knoten einen Replikatshard enthält, wodurch die Abfrageleistung verbessert wird, da auch Replikate zum Abfragen verwendet werden.

Die von Elasticsearch aus Gründen der Konsistenz verwendete Replikationsformel lautet:

(primär + anzahl_der_repliken) / 2 + 1

Zuordnung optimieren

Basierend auf den Produktdatenanforderungen können wir Daten in heiß und kalt klassifizieren. Indices, auf die häufiger zugegriffen wird als auf andere, können mehr Datenknoten zugewiesen werden, während Indices, auf die seltener zugegriffen wird, weniger Ressourcen zugewiesen bekommen können. Diese Strategie eignet sich besonders zum Speichern von Zeitreihendaten wie Anwendungsprotokollen (z. B. ELK).

Dies kann erreicht werden, indem ein Cronjob ausgeführt wird, der die Indizes in regelmäßigen Abständen auf verschiedene Knoten verschiebt.

Hot Node ist eine Art Datenknoten, der die gesamte Indizierung innerhalb des Clusters durchführt. Sie enthalten auch die neuesten Indizes, da diese in der Regel am häufigsten abgefragt werden. Da die Indizierung eine CPU- und E / A-intensive Operation ist, müssen diese Server leistungsfähig sein und durch angeschlossenen SSD-Speicher gesichert werden. Wir empfehlen, mindestens 3 Hot Nodes für hohe Verfügbarkeit zu betreiben. Je nachdem, wie viele aktuelle Daten Sie erfassen und abfragen möchten, müssen Sie diese Zahl möglicherweise erhöhen, um Ihre Leistungsziele zu erreichen.

Warm Node ist ein Datenknotentyp, der für die Verarbeitung einer großen Anzahl von Nur-Lese-Indizes ausgelegt ist, die mit geringer Wahrscheinlichkeit nicht häufig abgefragt werden. Da diese Indizes schreibgeschützt sind, werden bei Warm Nodes in der Regel große Festplatten (normalerweise rotierende Festplatten) anstelle von SSDs verwendet. Wie bei Hot Node empfehlen wir mindestens 3 Warm Node für hohe Verfügbarkeit. Und mit dem Vorbehalt, dass für größere Datenmengen möglicherweise zusätzliche Knoten erforderlich sind, um die Leistungsanforderungen zu erfüllen. Beachten Sie auch, dass CPU- und Speicherkonfigurationen häufig die Ihrer Hot Nodes spiegeln müssen. Dies kann nur durch Testen mit Abfragen ermittelt werden, die denen in einer Produktionssituation ähneln.

Weitere Details zu Hot- und Warm-Nodes finden Sie hier.

Eine andere Strategie, die Sie anpassen können, besteht darin, die Indizes in s3 zu archivieren und wiederherzustellen, wenn Sie Daten aus diesen Indizes benötigen. Hier können Sie mehr darüber lesen.

Knotentopologie:

Elasticsearch-Knoten können in drei Kategorien unterteilt werden: Masterknoten, Datenknoten, Client-Knoten.

  1. Masterknoten: Der Masterknoten kann klein sein, wenn er auch kein Datenknoten ist, da er keine Indizes / Shards speichert. Ihre Aufgabe ist es, detaillierten Clusterstatus und Hilfedaten und andere Knoten in der Index- / Shard-Metadaten-Suche zu speichern. Elasticsearch sollte mehrere Masterknoten haben, um Probleme mit dem geteilten Gehirn zu vermeiden.
  2. Datenknoten: Der Datenknoten ist für die Speicherung / Abfrage der aktuellen Indexdaten zuständig.
  3. Client-Knoten: Der Client-Knoten wird als Proxy für die Indizierung und Suche verwendet. Dies wird dringend empfohlen, wenn Aggregationen häufig verwendet werden. Hierbei handelt es sich um spezielle ElasticSearch-Knoten, für die weder Daten noch Master zulässig sind. Clientknoten sind clusterfähig und können daher als Smart Load Balancer eingesetzt werden. Sie können Ihre Abfragen an die Clientknoten senden, die dann die teure Aufgabe übernehmen, Antworten auf die Abfrageergebnisse von jedem der Datenknoten zu sammeln.

Fügen Sie diese Einstellungen zur Datei elasticsearch.yml für die jeweiligen Knoten hinzu.

Masterknoten: node.master: true node.data:false
Datenknoten: node.master: false node.data:true
Client-Knoten: node.master: false node.data:false

Tipps zur Fehlerbehebung:

Die Leistung von Elasticsearch hängt stark von der Maschine ab, auf der es installiert ist. CPU, Speichernutzung und Festplatten-E / A sind grundlegende Betriebssystemmetriken für jeden Elasticsearch-Knoten. Es wird empfohlen, die JVM-Metriken (Java Virtual Machine) zu untersuchen, wenn die CPU-Auslastung stark ansteigt. Im folgenden Beispiel war der Grund für den Anstieg eine höhere Speicherbereinigungsaktivität.

  1. Heap-Druck: Hoher Arbeitsspeicherdruck wirkt sich auf zwei Arten auf die Clusterleistung aus: Wenn der Arbeitsspeicherdruck auf 75% und mehr ansteigt, bleibt weniger Arbeitsspeicher verfügbar, und Ihr Cluster muss jetzt auch einige CPU-Ressourcen aufwenden, um Arbeitsspeicher durch Garbage Collection zurückzugewinnen. Diese CPU-Zyklen sind nicht für die Verarbeitung von Benutzeranforderungen verfügbar, während die Garbage Collection aktiviert ist. Infolgedessen erhöhen sich die Antwortzeiten für Benutzeranforderungen, wenn das System immer ressourcenbeschränkter wird. Wenn der Speicherdruck weiter ansteigt und nahezu 100% erreicht, wird eine viel aggressivere Form der Speicherbereinigung verwendet, was sich wiederum dramatisch auf die Cluster-Antwortzeiten auswirkt. Die Metrik der Indexantwortzeiten zeigt, dass ein hoher Speicherdruck zu einer erheblichen Beeinträchtigung der Leistung führt.
  2. Das Wachstum des Nicht-Heap-Speichers der JVM, das Aufzehren von Speicher für den Seiten-Cache und möglicherweise das Ernten von OOMs auf Kernel-Ebene.
  3. Vermeiden Sie Split-Brain-Probleme. Split Brain ist ein Szenario, in dem sich der Cluster aufteilt. Zum Beispiel haben Sie 6 Knoten-Cluster. 2 Knoten trennen sich vom Cluster, können sich jedoch weiterhin sehen. Diese beiden Knoten erstellen dann einen weiteren Cluster. Sie werden sogar einen neuen Meister unter sich wählen. Wir haben jetzt zwei Cluster mit demselben Namen, einen mit 4 Knoten und einen mit 2 Knoten. Jeder hat auch einen Hauptknoten. Dies wird als Split-Brain-Problem bei ES-Clustern bezeichnet. Um dies zu vermeiden, setzen Sie den ES-Parameter discovery.zen.minimum_master_nodes auf die Hälfte der Anzahl von Knoten + 1.
  4. Da Elasticsearch in hohem Maße Speichergeräte verwendet, wird durch die Überwachung der Festplatten-E / A sichergestellt, dass diese Grundbedürfnisse erfüllt werden. Es gibt viele Gründe für eine Reduzierung der Festplatten-E / A. Dies wird als Schlüsselmaß für die Vorhersage vieler Arten von Problemen angesehen. Es ist eine gute Metrik, um die Effektivität der Indizierung und die Abfrageleistung zu überprüfen. Die Analyse von Lese- und Schreibvorgängen zeigt direkt, was das System im jeweiligen Anwendungsfall am meisten benötigt. Die Betriebssystemeinstellungen für die Datenträger-E / A sind eine Grundlage für alle anderen Optimierungen. Durch die Optimierung der Datenträger-E / A können potenzielle Probleme vermieden werden. Wenn die Datenträger-E / A immer noch nicht ausreicht, sollten Gegenmaßnahmen wie das Optimieren der Anzahl und Größe der Shards, das Zusammenführen von Throttles, das Ersetzen langsamer Datenträger, das Verschieben auf SSDs oder das Hinzufügen weiterer Knoten je nach den Umständen, die die E / A verursachen, bewertet werden Engpässe.
  5. Bei Anwendungen, die auf der Suche basieren, hängt die Benutzererfahrung stark mit der Latenz von Suchanfragen zusammen. Es gibt viele Faktoren, die sich auf die Abfrageleistung auswirken können, z. B. erstellte Abfragen, falsch konfigurierte Elasticsearch-Cluster, Probleme mit dem JVM-Speicher und der Speicherbereinigung, Festplatten-E / A usw. Die Abfragelatenz ist die Metrik, die sich direkt auf Benutzer auswirkt. Stellen Sie daher sicher, dass Sie einige Warnungen darauf setzen.
  6. Die meisten Filter in Elasticsearch werden standardmäßig zwischengespeichert. Das bedeutet, dass Elasticsearch bei der ersten Ausführung einer gefilterten Abfrage Dokumente findet, die mit dem Filter übereinstimmen, und anhand dieser Informationen eine Struktur namens "Bitset" erstellt. Die im Bitset gespeicherten Daten enthalten eine Dokumentenkennung und ob ein bestimmtes Dokument mit dem Filter übereinstimmt. Bei nachfolgenden Ausführungen von Abfragen mit demselben Filter werden die im Bitset gespeicherten Informationen wiederverwendet, wodurch die Ausführung von Abfragen beschleunigt wird, indem E / A-Vorgänge und CPU-Zyklen gespart werden. Die Verwendung des Filters in der Abfrage wird empfohlen. Weitere Details finden Sie hier.
  7. Aktualisierungszeit und Zusammenführungszeit hängen eng mit der Indizierungsleistung zusammen und wirken sich auf die Gesamtleistung des Clusters aus. Die Aktualisierungszeit erhöht sich mit der Anzahl der Dateivorgänge für den Lucene-Index (Shard).
  8. Wenn Sie die Protokollierung langsamer Abfragen aktivieren, können Sie leichter ermitteln, welche Abfragen langsam sind und wie Sie sie verbessern können. Dies ist insbesondere bei Platzhalterabfragen hilfreich.
  9. Erhöhen Sie die ulimit-Größe, um maximal Dateien zuzulassen.
  10. Die Leistung von ElasticSearch kann beeinträchtigt werden, wenn das Betriebssystem den nicht verwendeten Anwendungsspeicher austauscht. Deaktivieren Sie das Auslagern, indem Sie Einstellungen auf Betriebssystemebene festlegen, oder legen Sie in der ElasticSearch-Konfiguration bootstrap.mlockall Folgendes fest: true
  11. Deaktivieren Sie das Löschen aller Indizes durch Platzhalterabfrage. Um sicherzustellen, dass niemand eine DELETE-Operation für alle Indizes (* oder _all) ausführt, setzen Sie action.destructive_requires_name auf true.

Bevor Sie fertig sind, finden Sie hier eine Liste von URLs, die zum Anzeigen der Metriken nützlich sind.

  • / _cluster / health? pretty: Für den Cluster-Integritätsindikator.
  • / _status? pretty: Für alle Informationen zu allen Indizes.
  • / _nodes? pretty: Für alle Informationen zu den Knoten.
  • / _cat / master? pretty: Für den Masterknoten.
  • / _stats? pretty: Für die Zuweisung von Shards werden die Statistiken indexiert.
  • / _nodes / stats? pretty: Für einzelne Knotenstatistiken sind dies JVM-, HTTP- und IO-Statistiken für den Knoten.

Die Metrikaggregation von Elasticsearch wird von den meisten Systemüberwachungstools wie Datadog und TICK unterstützt. Es wird empfohlen, solche Tools zu verwenden und einen Trichter zu erstellen, um Elasticsearch kontinuierlich zu überwachen.

Fazit:

Elasticsearch ist eine verteilte Volltextsuch- und Analyse-Engine, mit der mehrere Mandanten ihre gesamten Datensätze unabhängig von ihrer Größe mit beispielloser Geschwindigkeit durchsuchen können. Zusätzlich zu seinen Volltextsuchfunktionen fungiert ElasticSearch auch als Analysesystem und verteilte Datenbank. ElasticSearch verfügt über hervorragende Standardeinstellungen für den Einstieg. Sobald Sie die anfängliche Experimentierphase hinter sich haben, müssen Sie einige Zeit damit verbringen, die Einstellungen an Ihre Bedürfnisse anzupassen. Es wird empfohlen, dass Sie Ihre Konfiguration später zusammen mit der offiziellen Dokumentation erneut überprüfen, um sicherzustellen, dass Ihr Cluster Ihren Anforderungen entsprechend konfiguriert ist.