Indizierungsleistung in Solr 5.2 (jetzt doppelt so schnell)

Ungefähr um diese Zeit im letzten Jahr (Juni 2014) habe ich das Solr Scale Toolkit vorgestellt und einige Kennzahlen zur…

Ungefähr um diese Zeit im letzten Jahr (Juni 2014) habe ich das Solr Scale Toolkit vorgestellt und einige Kennzahlen zur Indizierungsleistung für Solr 4.8.1 veröffentlicht. Solr 5.2.0 wurde gerade veröffentlicht und enthält einige spannende Verbesserungen der Indizierungsleistung, insbesondere bei der Verwendung von Replikation. Bevor wir uns im Detail mit den Verbesserungen befassen, lassen Sie uns sehen, wie sich die Dinge empirisch verbessert haben.

Mit Solr 4.8.1, das in EC2 läuft, konnte ich 130 Mio. Dokumente in einer Sammlung mit 10 Shards und einem Replikationsfaktor von 2 in 3.727 Sekunden (~62 Minuten) mit zehn r3.2xlarge-Instanzen indizieren; Einzelheiten zu dem Datensatz finden Sie in meinem vorherigen Blogbeitrag. Dies entspricht einem durchschnittlichen Durchsatz von 34.881 Dokumenten/Sekunde. Heute, unter Verwendung desselben Datensatzes und derselben Konfiguration, mit Solr 5.2.0, wurde der Auftrag in 1.704 Sekunden (~28 Minuten) abgeschlossen, was einem durchschnittlichen Durchsatz von 76.291 Dokumenten/Sek. entspricht. Um Anomalien auszuschließen, habe ich diese Ergebnisse beim Testen der Release Candidates für 5.2 mehrmals reproduziert. Der einzige nennenswerte Unterschied zwischen den beiden Tests ist, dass Lucene und Solr ein Jahr lang verbessert wurden!

Kommen wir nun zu den Details, was wir behoben haben. Zunächst einmal kann ich nicht genug betonen, wie viel harte Arbeit und scharfsinnige Überlegungen in die Verbesserung von Lucene und Solr im letzten Jahr geflossen sind. Ein besonderer Dank geht auch an die Solr-Committer Mark Miller und Yonik Seeley, die mir geholfen haben, die in diesem Beitrag angesprochenen Probleme zu identifizieren, mögliche Lösungen vorzuschlagen und mich bei der Ausarbeitung der Implementierungsdetails zu unterstützen. Eines der großartigen Dinge an der Arbeit an einem Open-Source-Projekt ist die Möglichkeit, das Fachwissen anderer Entwickler zu nutzen, wenn man an einem schwierigen Problem arbeitet.

Zu viele Anfragen an Replikate

Eine der wichtigsten Beobachtungen bei meinen Indizierungstests im letzten Jahr war, dass die Replikation einen höheren Overhead verursacht, als man erwarten würde. Bei der Indizierung in 10 Shards ohne Replikation erreichte der Test beispielsweise durchschnittlich 73.780 Dokumente/Sekunde, aber mit Replikation sank die Leistung auf 34.881. Sie werden auch feststellen, dass ich nach der Aktivierung der Replikation die Anzahl der Reducer-Tasks (von 48 auf 34), mit denen ich Dokumente von Hadoop an Solr schickte, verringern musste, um zu vermeiden, dass die Replikate während der Indizierung großer Mengen in den Recovery-Modus gehen. Einfach ausgedrückt: Mit aktivierter Replikation konnte ich Solr nicht mehr so stark beanspruchen.

Als ich anfing, die Gründe für die hohen Kosten der Replikation zu untersuchen, entdeckte ich unter anderem, dass die Replikate bei der Verarbeitung von Batch-Updates bis zu 40 Mal mehr Aktualisierungsanfragen von ihrem Leader erhalten. Dies ist in den Leistungsmetriken für alle Request-Handler im Statistik-Panel in der Solr-Administrationsoberfläche zu sehen.

Das Stapeln von Dokumenten in einer einzigen Anfrage ist eine gängige Strategie, die von Client-Anwendungen verwendet wird, die einen hohen Indizierungsdurchsatz benötigen. Die an einen Shard-Leader gesendeten Stapel werden jedoch auf dem Leader in einzelne Dokumente zerlegt, lokal indiziert und dann mit ConcurrentUpdateSolrClient zu den Replikaten gestreamt. Mehr über die Details des Problems und die Lösung erfahren Sie in SOLR-7333. Einfach ausgedrückt, verursachte die Replikationsstrategie von Solr eine viel höhere CPU-Last auf den Replikaten als auf den Leadern, wie Sie in den Screenshots unten sehen können.

CPU-Profil auf Leader

führer_cpu

CPU-Profil auf Replikat (viel höher als Leader)

Replikat_cpu

Idealerweise möchten Sie, dass alle Server in Ihrem Cluster in etwa die gleiche CPU-Auslastung haben. Die in SOLR-7333 beschriebene Lösung hilft, die Anzahl der Anfragen und die CPU-Last auf den Replikaten zu reduzieren, indem mehr Dokumente vom Leader pro Anfrage gesendet werden, wenn ein Stapel von Aktualisierungen verarbeitet wird. Beachten Sie jedoch, dass die Batch-Optimierung nur verfügbar ist, wenn Sie das JavaBin-Anforderungsformat verwenden (das Standardformat, das von CloudSolrClient in SolrJ verwendet wird). Wenn Ihre Indizierungsanwendung Dokumente in einem anderen Format (JSON oder XML) an Solr sendet, können die Shard-Leader diese Optimierung beim Streaming von Dokumenten an die Replikate nicht nutzen. Wir werden wahrscheinlich in naher Zukunft eine ähnliche Lösung für die Verarbeitung anderer Formate hinzufügen.

Versionsverwaltung Lock Contention

Solr fügt jedem Dokument ein Feld _version_ hinzu, um die optimistische Gleichzeitigkeitskontrolle zu unterstützen. Hinter den Kulissen verwendet das Transaktionsprotokoll von Solr ein Array von Versions-„Buckets“, um die höchste bekannte Version für einen Bereich von gehashten Dokument-IDs festzuhalten. So kann Solr erkennen, ob eine Aktualisierungsanfrage veraltet ist und verworfen werden sollte.

Mark Miller hat seine eigenen Indizierungsleistungstests durchgeführt und festgestellt, dass teure Index-Housekeeping-Operationen in Lucene einen Solr-Indizierungs-Thread abwürgen können. Wenn dieser Thread zufällig die Sperre für einen Versions-Bucket hält, kann er andere Threads, die um die Sperre konkurrieren, abwürgen. Um dieses Problem zu beheben, haben wir die Standardanzahl der Versionsbereiche, die von den Transaktionsprotokollen von Solr verwendet werden, von 256 auf 65536 erhöht, was dazu beiträgt, die Anzahl der gleichzeitigen Anfragen zu reduzieren, die blockiert werden, während sie darauf warten, die Sperre für einen Versionsbereich zu erhalten. Mehr über dieses Problem und die Lösung erfahren Sie in SOLR-6820. Wir prüfen noch, wie wir damit umgehen, dass Lucene den Indizierungsthread für teure Hintergrundoperationen verwendet, aber im Moment ist das weniger ein Problem.

Teure Suche nach der Version eines Dokuments

Beim Hinzufügen eines neuen Dokuments setzt der Leader das Feld _version_ auf einen langen Wert, der auf der CPU-Uhrzeit basiert. Übrigens sollten Sie für alle Server in Ihrem Solr-Cluster einen Uhrensynchronisationsdienst verwenden. Mit dem YourKit Profiler habe ich festgestellt, dass die Replikate viel Zeit damit verbrachten, die _version_ für neue Dokumente nachzuschlagen, um sicherzustellen, dass die Aktualisierungsanfragen nicht neu geordnet wurden. Der kostspielige Code war insbesondere dort, wo Solr versucht, die interne Lucene-ID für eine bestimmte Dokument-ID zu finden. Für neue Dokumente gibt es natürlich keine existierende Version, so dass Solr eine Menge Arbeit damit vergeudete, nach Dokumenten zu suchen, die gar nicht existierten.

Yonik wies darauf hin, dass wir, wenn wir die vom Transaktionsprotokoll verwendeten Versions-Buckets mit dem Maximalwert des Feldes _version_ initialisieren, bevor wir neue Aktualisierungen akzeptieren, diese kostspielige Suche für jedes neue Dokument, das in der Replik ankommt, vermeiden können. Mit anderen Worten: Wenn ein Versions-Bucket mit dem Maximalwert aus dem Index gefüttert wird, wissen wir, wenn neue Dokumente mit einem Versionswert ankommen, der größer ist als der aktuelle Maximalwert, dass diese Aktualisierungsanfrage nicht neu geordnet wurde. Natürlich wird die maximale Version für jeden Bucket aktualisiert, wenn neue Dokumente in Solr eingehen.

Daher werden ab Solr 5.2.0 bei der Initialisierung eines Solr-Kerns die Versions-Buckets mit der höchsten bekannten Version aus dem Index gefüllt (siehe SOLR-7332 für weitere Details). Mit diesem Fix kann ein Replikat, wenn es ein Dokument von seinem Leader erhält, schnell feststellen, ob die Aktualisierung neu geordnet wurde, indem es den höchsten Wert des Versions-Buckets für dieses Dokument abfragt (basierend auf einem Hash der Dokument-ID). In den meisten Fällen hat die Version eines bei einer Replik eingehenden Dokuments einen höheren Wert als der Versionsbereich, was eine teure Suche im Lucene-Index erspart und den Gesamtdurchsatz der Replikate erhöht. Wenn das Replikat zufällig eine Version sieht, die niedriger ist als der maximale Wert im Bucket, muss es trotzdem den Index konsultieren, um sicherzustellen, dass die Aktualisierung nicht neu geordnet wurde.

Diese drei Tickets zusammengenommen bewirken eine erhebliche Steigerung der Indizierungsleistung und ermöglichen es uns, Solr jetzt noch stärker zu nutzen. Konkret konnte ich mit Solr 4.8.1 nur 34 Reducer verwenden, aber mit 5.2.0 konnte ich 44 Reducer verwenden und trotzdem stabil bleiben.

Wenn Sie sich fragen, was Sie tun müssen, um von diesen Verbesserungen zu profitieren, brauchen Sie nur auf Solr 5.2.0 zu aktualisieren, es sind keine zusätzlichen Konfigurationsänderungen erforderlich. Ich hoffe, dass Sie diese Verbesserungen in Ihrer eigenen Umgebung nutzen können und bitte Sie, JIRA-Anfragen einzureichen, wenn Sie weitere Ideen zur Verbesserung der Solr-Indizierungsleistung haben. Das Solr Scale Toolkit wurde aktualisiert, um Solr 5.2.0 zu unterstützen, und der von mir verwendete Datensatz ist öffentlich auf S3 verfügbar, falls Sie diese Ergebnisse reproduzieren möchten.

You Might Also Like

B2B-KI-Benchmarkstudie 2025: Was wir in den Schützengräben sehen

Laden Sie die B2B-KI-Benchmark-Highlights 2025 von Lucidworks herunter. Sehen Sie sich die...

Read More

Vom Suchunternehmen zum praktischen KI-Pionier: Unsere Vision für 2025 und darüber hinaus

CEO Mike Sinoway gibt Einblicke in die Zukunft der KI und stellt...

Read More

Wenn KI schief geht: Fehlschläge in der realen Welt und wie man sie vermeidet

Lassen Sie nicht zu, dass Ihr KI-Chatbot einen 50.000 Dollar teuren Tahoe...

Read More

Quick Links