ElasticSearch-setup für eine große Gruppe mit starken Aggregationen
Kontext und den aktuellen Stand
Sind wir die Migration unserer cluster von Cassandra zu einem vollen ElasticSearch-cluster. Wir sind der Indizierung von Dokumenten auf durchschnittlich ~250-300 docs pro Sekunden. In ElasticSearch 1.2.0 stellt es ~8Go pro Tag.
{
"generic":
{
"id": "twi471943355505459200",
"type": "twitter",
"title": "RT @YukBerhijabb: The Life is Choice - https://m.facebook.com/story.php?story_fbid=637864496306297&id=100002482564531&refid=17",
"content": "RT @YukBerhijabb: The Life is Choice - https://m.facebook.com/story.php?story_fbid=637864496306297&id=100002482564531&refid=17",
"source": "<a href=\"https://twitter.com/download/android\" rel=\"nofollow\">Twitter for Android</a>",
"geo": null,
"link": "http://twitter.com/rosi_sifah/status/471943355505459200",
"lang": "en",
"created_at": 1401355038000,
"author": {
"username": "rosi_sifah",
"name": "Rosifah",
"id": 537798506,
"avatar": "http://pbs.twimg.com/profile_images/458917673456238592/Im22zoIV_normal.jpeg",
"link": "http://twitter.com/rosi_sifah"
}
},
"twitter": {
//a tweet JSON
}
}
Unseren Benutzern das speichern von Anfragen in unsere SQL-Datenbank und, wenn Sie bitten, für Ihre dashboard würden wir gerne auf Wunsch unsere ES-Clusters mit Ihrer Abfrage (abgerufen aus der Datenbank) und einige aggregation oben drauf mit dem neuen ES-aggregation framework.
Jedes dashboard angezeigt wird, mit einer expliziten, vom Benutzer gewählten, Datum, Angebot, also wir verwenden immer
"range": {
"generic.created_at": {
"from": 1401000000000,
"to": 1401029019706
}
}
zusammen mit der ES-query.
Wir angegeben _routing so:
"_routing":{
"required":true,
"path":"generic.id"
},
und die _id mit:
"_id": {
"index": "not_analyzed",
"store": "false",
"path": "generic.id"
}
Etwa 5 Tage, die wir gespeichert haben 67 Millionen Dokumente (über 40Go) in einem index. Wir haben erfahren über die gute Praxis der spliting der index von Tag zu Tag. So, jetzt unsere Indizes sind aufgeteilt in den Tag ([index-name]-[JJJJ-MM-TT]).
Derzeit jeder index hat 5 shards und 1 replica, wir haben einen cluster bestehend aus 3 Maschinen mit je 8 Kernen, 16Go RAM und 8To von HDD. Wir planen, verwenden Sie eine andere Maschine als gateway (8 Kerne, 16Go RAM, 1 HDD).
Wir haben die Winterlinde ES-Konfiguration standardmäßig neben der cluster-Konfiguration.
Fragen
- Für jedes Dokument, das wir indizieren wollen, sagen wir ausdrücklich, was index
verwenden. Derzeit verwenden wir das Datum des Tages. Sollten wir das Datum des
das Dokument, um zu verhindern, dass hot-spot? Denn derzeit es
bedeutet, dass die Dokumente von verschiedenen Tagen (angegeben in Ihren
created_at) Leben können, in den gleichen index des aktuellen Tages. - Sind 5 Scherben genug (oder zu viel) für 21 600 000 Dokumente durch den Tag?
- Wenn wir wollen, dass alle unsere aggregierte Abfragen verarbeitet werden, in weniger als 1 Sekunde, wie viele Replik sollten wir setup up?
- Sollten wir ändern unser routing? Da wir nicht wissen, vor der Zeit, die Dokumente verarbeitet werden, bevor die aggregation für jede Anfrage, die wir dem cluster (da die Abfrage wird vom Benutzer definiert)
- Welche Art von hardware (wie viele Maschinen, welche Konfiguration), sollten wir in diesem cluster zu unterstützen, 6 Monate von Dokumenten?
[Update]
Ist hier einige Beispiel-Abfragen:
Einer word-cloud
GET idx-2014-05-01/stream/_search?search_type=count
{
"query":{
"bool": {
"must": [{
"query_string" : {
"query" : "(generic.lang:fr OR generic.lang:en) AND (generic.content:javascript)"
}},{
"range": {
"generic.created_at": {
"from": 1401000000000,
"to": 1401029019706
}
}}
]
}
},
"aggs":{
"words":{
"terms":{
"field": "generic.content",
"size": 40
}
}
}
}
Einem Histogramm
GET idx-2014-05-01/stream/_search?search_type=count
{
"query":{
"bool": {
"must": [{
"query_string" : {
"query" : "generic.content:apple"
}},{
"range": {
"generic.created_at": {
"from": 1401000000000,
"to": 1401029019706
}
}}
]
}
},
"aggs":{
"volume":{
"date_histogram":{
"field": "generic.created_at",
"interval":"minute"
}
}
}
}
Muss die verwendete Sprache
GET idx-2014-05-01/stream/_search?search_type=count
{
"query":{
"bool": {
"must": [{
"query_string" : {
"query" : "(generic.lang:fr OR generic.lang:en) AND (generic.content:javascript)"
}},{
"range": {
"generic.created_at": {
"from": 1401000000000,
"to": 1401029019706
}
}}
]
}
},
"aggs":{
"top_source":{
"terms":{
"field": "generic.lang"
}
}
}
}
- Wie habt Ihr das gelöst? Ich bin auch konfrontiert mit aggregation-heavy-Abfragen, die schlecht durchführen. Was sind die Parameter, die wir optimieren können um die situation zu verbessern? Ich denke irgendwie die Verringerung der Anzahl der buckets erstellt für jede aggregation (z.B., shard_min_doc_count - parameter) oder vielleicht die Erhöhung der Zahl der Scherben, so dass jeder shard hat zu aggregieren weniger Daten? Alle Zeiger?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Lassen Sie mich Vorwort alle meine Antworten/Kommentare mit dem Rat zu versuchen, so viel wie möglich, testen Sie diese Szenarien selbst. Während Elasticsearch ist sehr skalierbar, es gibt viele Kompromisse, die sind stark belastet durch-Dokument, Größe und Typ, Einspielung und Abfrage-volume, die hardware und das Betriebssystem. Zwar gibt es viele falsche Antworten gibt es selten eine richtige Antwort.
Ich stützt diese Antwort auf ein paar aktiv-Cluster mit mit (derzeit) etwa eine halbe million aktive Dokumente in Ihnen, plus einige der jüngsten benchmarking führten wir etwa 4X Volumen (rund 80 MILLIONEN Dokumente pro Tag aufgenommen während der benchmark).
1) First off, Sie schaffen nicht viel von einem hot-spot mit 3 Knoten, wenn Sie einen index mit 5 shards und 1 replica pro shard. Elasticsearch wird, trennen Sie die einzelnen Replik aus, es ist primär auf einen anderen Knoten, und im Allgemeinen wird versuchen, zum Ausgleich der Belastung von Scherben. Elasticsearch per default wird die hash-ID zu Holen den shard-index in (die dann kopiert wird, um das Replikat). Selbst mit routing, Sie haben nur eine hot-spot-Problem, wenn man einzelne IDs, erstellen einer großen Anzahl von Dokumenten pro Tag (das ist die Spanne des index). Selbst dann, wäre es kein problem, es sei denn, diese IDs produzieren einen erheblichen Anteil des Volumens UND es gibt so wenige von Ihnen, dass Sie bekommen konnte Verklumpung auf nur 1 oder 2 Scherben.
Nur Sie können bestimmen, dass basierend auf der Verwendung des Muster - ich würde vorschlagen, sowohl eine Analyse Ihrer bestehenden Datensatz zu suchen, zu große Konzentrationen und eine Analyse der wahrscheinlichen Abfragen.
Einer größeren Frage, die ich habe, ist die Art Ihrer Fragen. Sie sind nicht mit dem vollständigen Abfrage noch das vollständige schema (sehe ich "generic.id" verwiesen, aber nicht in der Dokument-schema, und die Abfrage zeigt, ziehen Sie jedes einzelne Dokument innerhalb eines Zeit-Bereich - ist das richtig?). Benutzerdefiniertes routing für die Indizierung ist besonders nützlich, wenn Sie Ihre Abfragen gebunden sind, durch eine genaue übereinstimmung auf dem Feld verwendet, für das routing. Also, wenn ich hatte einen index mit allen Unterlagen in meine Abfrage Muster war nur abrufen eines einzelnen Benutzers Dokument in einer einzigen Abfrage, dann benutzerdefinierte routing von Benutzer-id wäre sehr nützlich, um die Abfrageleistung zu verbessern und reduzieren die gesamte cluster-Last.
Eine zweite Sache zu prüfen, ist der gesamte Saldo der Einnahme vs. Abfragen. Sie sind Einnahme über 20M Dokumente pro Tag - wie viele Abfragen du ausführen pro Tag? Wenn diese Zahl ist <<< die Einnahme beurteilen Sie, möchten Sie vielleicht denken, durch die Notwendigkeit für eine benutzerdefinierte route. Auch, wenn die query-performance ist gut oder groß, können Sie nicht wollen, fügen Sie die zusätzliche Komplexität.
Schließlich auf die Indizierung durch Verschlucken Datum vs. created_at. Wir haben gekämpft mit, dass man auch da haben wir etwas Verzögerung in den Erhalt von neuen Unterlagen. Für heute haben wir uns mit der Speicherung von Aufnahme-Datum, da es einfacher zu verwalten und nicht zu einem großen Problem für Abfrage mehrere Indizes in einer Zeit, besonders, wenn Sie auto-Aliase erstellen für 1 Woche, 2 Wochen, 1 Monat, 2 Monate, etc.. Ein größeres Problem ist, was die Verteilung ist - wenn Sie Dokumente haben, die kommen Wochen oder Monate später, möchten Sie vielleicht zu ändern, um die Indexierung durch created_at aber das wird erfordern, halten die Indizes online, und öffnen Sie für einige Zeit.
Wir verwenden derzeit mehrere Dokument-Indizes, die pro Tag, im Grunde "--" format. Praktisch heißt dies gegenwärtig 5 Indizes pro Tag. Dies ermöglicht uns, mehr selektiv zum verschieben von Daten in und aus dem cluster. Nicht eine Empfehlung für Sie nur etwas, das wir gelernt haben, ist nützlich für uns.
2) Hier ist das große denken über ES - mit einen neuen index erstellen, jeden Tag können Sie anpassen, wie die Zeit vergeht zur Steigerung der Zahl der Scherben pro index. Während Sie nicht ändern können Sie für einen vorhandenen index, die Sie erstellen, jeden Tag eine neue und Sie stützen Ihre Entscheidung auf die Reale Produktion und Analytik. Sie wollen sicher zu beobachten, die Anzahl und vorbereitet werden, um die Zahl der Scherben, als/wenn Sie die Einnahme pro Tag erhöht. Es ist nicht der einfachste Kompromiss - jeder dieser Scherben ist ein Lucene-Instanz, die möglicherweise mehrere Dateien. Mehr Splitter pro index ist nicht frei, wie das potenziert sich mit der Zeit. Angesichts Ihrer Verwendung bei 6 Monaten, das sind über 1800 Scherben öffnen Sie über 3 Knoten (182 Tage x 5 Grundfarben und 5 Replikate pro Tag). Es gibt ein Vielfaches von Dateien pro shard wahrscheinlich offen. Wir haben festgestellt, dass einige level von Aufwand und Auswirkungen auf die Ressourcennutzung auf unsere Knoten als Gesamt-Splitter Anzahl erhöht sich im cluster in diesen Bereichen. Ihre Laufleistung kann variieren, aber ich würde vorsichtig sein, über die Erhöhung der Zahl der Scherben pro index, wenn Sie planen, halten 182 Indizes (6 Monate) in einer Zeit - das ist schon ein Multiplikator. Ich würde auf jeden Fall benchmark, der vor der Zeit, wenn Sie änderungen an der Standard-Splitter zählen.
3) Es gibt keine Weise, jemand kann Vorhersagen, Abfrage-performance vor der Zeit für Sie. Es basiert auf die gesamte cluster-Last, Komplexität der Abfrage, Abfrage-Frequenz, hardware, etc. Es ist sehr spezifisch für Ihre Umgebung. Sie gehen zu müssen, zu diesem benchmark. Persönlich gegeben haben, dass Sie die bereits geladenen Daten, die ich verwenden würde, das ES Snapshots und wiederherstellen, um diese Daten in eine Testumgebung zu testen. Versuchen Sie es mit dem Standardwert 1 replica und sehen, wie es geht. Hinzufügen replica shards ist ideal für Daten-Redundanz und kann helfen, sich auszubreiten Abfragen über die cluster aber es kommt zu einem eher hohen Preis - 50% mehr Speicher-plus jede weitere Replik-Splitter bringt zusätzliche Einnahme Kosten auf den Knoten ausgeführt wird. Es ist großartig, wenn Sie müssen die Redundanz und spare die Kapazität, nicht so toll, wenn Sie nicht über ausreichende Abfrage der Lautstärke, um wirklich nutzen es.
4) Ihre Frage ist unvollständig (es endet mit "wir haben nie"), so kann ich nicht beantworten, es direkt - aber eine größere Frage ist, warum sind Sie benutzerdefinierte routing zu beginnen? Sicher, es kann große performance-Vorteile, aber es ist nur nützlich, wenn Sie ein segment aus einem Satz von Dokumenten von dem Feld, das Sie verwenden, um die route. Es ist nicht ganz klar aus deinen Beispiel-Daten und-teilweise-Abfrage, wenn das der Fall ist. Ich persönlich würde es testen, ohne benutzerdefinierte routing-und dann versuchen Sie das gleiche mit ihm und sehen, ob es signifikante Auswirkungen hat.
5) eine Andere Frage, die verlangen, dass einige Arbeit auf Ihrer Seite. Sie müssen sich um (mindestens) die JVM-heap-Verwendung, die gesamte Speicher-und cpu-Auslastung, Festplattennutzung und disk-io-Aktivität über die Zeit. Wir tun, mit Schwellenwerten, die warnen auch vor zu sehen, Fragen, so dass wir können neue Mitglieder hinzufügen, um die cluster zu früh. Beachten Sie, dass beim hinzufügen eines Knotens zu einem cluster ES ist zu gehen, um zu versuchen, um re-balance cluster. Läuft die Produktion mit nur 3 Knoten mit einem großen erste-Dokument festlegen, können Probleme verursachen, wenn Sie verlieren einen Knoten, um Probleme (Heap Erschöpfung, JVM-Fehler, hardware-Fehler, Netzwerk-Ausfall, etc.). ES ist Gelb und dort zu bleiben für einige Zeit, während es Umbesetzungen.
Persönlich für großes Dokument zahlen und hohe Einnahme würde ich anfangen das hinzufügen von Knoten früher. Mit mehr Knoten im Ort ist es weniger ein Problem, wenn Sie einen Knoten für die Wartung. Über Ihre bestehende Konfiguration, wie kamst du zu 8 TB HDD pro node? Gegeben eine Einnahme von 8GB pro Tag, das scheint wie overkill für 6 Monate Daten. Ich würde stark vermuten, dass angesichts der Datenmenge und der Anzahl der Indizes/Scherben Sie verschieben möchten, um mehr Knoten, die noch weiter reduzieren Sie Ihre Speicher pro Knoten Anforderung.
Ich würde auf jeden Fall wollen die benchmark eine maximale Anzahl der Dokumente pro Knoten, indem die Schleife-thru-high volume Verschlucken und Schleifen der normalen Abfrage-Frequenz auf einem cluster mit nur 1 oder 2 Knoten und sehen, wo es scheitert (entweder in der Leistung, heap Erschöpfung oder andere Ausgabe). Ich würde dann die Planung um die Anzahl der Dokumente pro Knoten deutlich unter dieser Zahl.
Alle, die sagte, ich würde gehen aus dem Fenster lehnen und sagen, dass ich bezweifle, Sie werden alle so glücklich mit 4 Milliarden plus Dokumente auf 3 16GB Knoten. Selbst wenn es funktionierte (wieder, test, test, test) verliert ein Knoten geht um ein wirklich großes Ereignis. Ich persönlich mag die kleineren Knoten, sondern bevorzugen viele von Ihnen.
Anderen Gedanken - wir zunächst ein Benchmark auf 3 Amazon EC2 m1.xlarge Instanzen (4 cores, 15 GB Speicher), die fein gearbeitet, über mehrere Tage nach der Einnahme auf 80M Dokumente am Tag, die größere Durchschnittliche Größe der Dokumente, als Sie zu haben scheinen. Größte Problem war die Anzahl der Indizes und shards öffnen (wir waren die Schaffung von ein paar hundert neue Indizes pro Tag mit vielleicht ein paar tausend mehr Splitter pro Tag, und dies war das erstellen von Fragen). Wir haben seit ein paar Hinzugefügt neue Knoten mit 30GB Speicher und 8 Kernen und dann noch 80M-Dokumente zu testen. Unsere aktuelle Produktion-Ansatz ist, halten Sie lieber mehr allzu großen Knoten im Gegensatz zu wenigen großen.
UPDATE:
Bezüglich der benchmarking-hardware, es wurde wie oben angegeben getestet auf 3 Amazon EC2 m1.xlarge virtuelle Instanzen läuft ubuntu 12.04 LTS und ES 1.1.0. Wir liefen auf über 80 MILLIONEN Dokumente pro Tag (ziehen Sie Daten aus einer MongoDB Datenbank, die wir zuvor benutzt hatten). Jede Instanz hatte 1 TB Speicherplatz über Amazon EBS mit Bestimmung IOPS von ich glaube 1000 IOPS. Wir liefen für ungefähr 4-5 Tage. Wir haben schon ein bisschen cpu-eingeschränkt auf 80M am Tag und glauben, dass mehr Knoten würde erhöht haben unsere Einnahme-rate. Als der benchmark lief und die Anzahl der Indizes und shards erhöht, sahen wir die Erhöhung der Speicherauslastung. Wir erstellten eine große Anzahl von Indizes und shards (etwa 4 -5 Indizes pro 1 M-Dokumente oder-über 400 Indizes pro Tag, mit 5 primären shards und 1 replica Shards pro index).
Bezüglich der index-Aliasnamen, die wir schaffen, über einen cron-Eintrag rolling-index-Aliasnamen für 1 Woche zurück, 2 Wochen zurück, etc, so dass unsere Anwendung können Sie einfach auf einen bekannten index alias und laufen immer gegen ein set time frame heute zurück. Wir sind mit dem index-Aliase rest-api zum erstellen und löschen Sie Sie:
http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-aliases.html