Indizierung mit hohem Durchsatz in Solr
Manchmal müssen Sie eine ganze Reihe von Dokumenten sehr, sehr schnell indizieren. Selbst mit Solr 4.0 und Soft Commits sind…
Manchmal müssen Sie eine ganze Reihe von Dokumenten sehr, sehr schnell indizieren. Selbst mit Solr 4.0 und Soft Commits sind Sie durch das Netzwerk eingeschränkt, wenn Sie nur ein Dokument nach dem anderen senden. Die Lösung ist zweifach: Batching und Multi-Threading. Batching hilft Ihnen, Netzwerklatenzen zu überwinden, und Multi-Threading hilft Ihnen, Solr vollständig mit Aktualisierungen zu sättigen. Dies gilt insbesondere, wenn Sie CloudSolrServer
oder LBHttpSolrServer
verwenden, die Ihre Aktualisierung an einen von vielen Solr-Servern weiterleiten.
Nehmen wir zunächst an, dass Sie eine Warteschlange mit Strings haben, die das „Text“-Feld der Solr-Dokumente werden soll (das Auffüllen der Warteschlange überlasse ich dem Leser als Übung). Um Speicher und Garbage Collection zu sparen, können wir ein einziges SolrInputDocument
und UpdateRequest
pro Thread wiederverwenden.
[gist id=“4627882″]
Der obige Code wird ewig laufen, da wir BlockingQueue#take
verwenden.
Da wir nun über einfaches Multi-Threading verfügen, besteht der nächste Schritt darin, die Aktualisierungen zu stapeln. Dies erfordert eine sehr kleine Änderung an unserer Klasse SolrUpdater
. Die Stapelverarbeitung ist recht einfach, da UpdateRequest#add
es Ihnen ermöglicht, Dokumente einzeln hinzuzufügen (die eigentliche Anfrage wird erst beim Aufruf der process-Methode gestellt).
[gist id=“4627896″]
Wir können ein einzelnes SolrInputDocument
nicht mehr wiederverwenden, da wir sie in der UpdateRequest stapeln, aber wir können immer noch die UpdateRequest
wiederverwenden. Sobald wir unsere Stapelgröße erreicht haben, senden wir die Anfrage tatsächlich ab. Natürlich müssen Sie die Stapelgröße und die Anzahl der Threads abhängig von der Größe Ihrer Dokumente, der Anzahl der Solr-Server, den Kosten für die Indizierung usw. anpassen.
Seien Sie gewarnt, diese Implementierung ist bei weitem nicht vollständig. Es gibt keine Thread-Verwaltung, Fehlerbehandlung, Protokollierung, Überwachung oder andere Dinge, die Sie für eine robuste Multithreading-Anwendung benötigen. Es gibt sogar einen schwerwiegenden Fehler in Bezug auf den Datenverlust: Wenn Sie diese Threads beenden, gehen alle nicht übertragenen Dokumente einfach verloren.
Bei Lucidworks haben wir eine ähnliche (wenn auch vollständigere) Implementierung verwendet, um unseren Indexierungsdurchsatz um eine Größenordnung zu steigern.