- Discord hat die gesamte Struktur auf Kubernetes-Basis neu entworfen, um die Grenzen der bestehenden Elasticsearch-basierten Suchinfrastruktur zu überwinden, und dabei Leistung und Stabilität der Nachrichtenindexierung deutlich verbessert
- Die bisherige Redis-Queue barg das Risiko von Nachrichtenverlusten, wurde aber durch PubSub ersetzt, das eine zuverlässige Nachrichtenübermittlung gewährleistet; gleichzeitig werden Nachrichten nach Cluster und Index klassifiziert und effizient verarbeitet
- Durch die Einführung einer „Cell“-Architektur mit vielen kleinen Elasticsearch-Clustern wurden Probleme wie Node-Überlastung und nicht mögliche Updates gelöst
- Private DM-Nachrichten und Server-(Guild-)Nachrichten werden in separaten Cells indexiert, was die Grundlage für die neu eingeführte plattformweite DM-Suche bildet
- Für extrem große Communities (BFGs) ermöglichen dedizierte Cells und Multi-Shard-Indizes eine Skalierung über Lucenes maximale Nachrichtenanzahl hinaus
Grenzen der bisherigen Infrastruktur
- Die Redis-basierte Nachrichten-Queue wurde bei Ausfällen von Elasticsearch-Nodes zum Engpass, mit der Möglichkeit von Nachrichtenverlusten
- In großen Clustern mit mehr als 200 Nodes führte bereits der Ausfall eines einzelnen Nodes zu einer Fehlschlagrate von 40 % bei der gesamten Indexierung
- Indizes, die Lucenes Limit
MAX_DOCS (2 Milliarden Nachrichten) erreichten, führten zu einem vollständigen Stopp der Indexierung
- Aufgrund des veralteten Systems war selbst ein log4shell-Patch nur nach vollständigem Offline-Nehmen des Systems möglich
Lösungsstrategie
Neuaufbau auf Kubernetes-Basis
- Einsatz des Elastic Kubernetes Operator (ECK) zur Automatisierung des Betriebs von Elasticsearch-Clustern
- Rolling Restarts sowie OS- und Software-Upgrades sind dadurch sicher möglich
Verteilung der Cluster mit einer „Cell“-Architektur
- Statt eines bisherigen großen Einzel-Clusters besteht eine Cell aus mehreren kleinen Clustern
- Innerhalb jeder Cell wird die Anzahl der Indizes begrenzt und die Shard-Größe unter 50 GB sowie unter 200 Millionen Nachrichten gehalten
- Bessere Indexierungs- und Query-Performance sowie geringerer Aufwand zur Aufrechterhaltung des Cluster-Zustands
PubSub-basierte Nachrichten-Queue
- Durch die Umstellung von Redis → PubSub kann die Warteschlange ohne Nachrichtenverlust aufrechterhalten werden
- Der Einsatz von PubSub wird auch auf andere Funktionen wie Job Scheduling ausgeweitet
Batch-Indexierung pro Cluster
- Über PubSub empfangene Nachrichten werden nach Ziel-Cluster und Index klassifiziert und in separaten Tasks parallel verarbeitet
- Umsetzung einer Architektur zur verteilten Nachrichtenverarbeitung mit Rusts
tokio-Tasks und Channels
Verbesserungen der Suchfunktion
Nutzerbasierte DM-Suche
- Zuvor wurden DMs pro Kanal indexiert, wodurch eine Suche über alle DMs hinweg ineffizient war
- Jetzt werden DM-Nachrichten zusätzlich in nutzerspezifischen Indizes doppelt indexiert, sodass alle DMs auf einmal durchsucht werden können
Umgang mit BFGs (Big Freaking Guilds)
- Für extrem große Communities, die Lucenes Nachrichtenlimit überschreiten, wurden Multi-Shard-Indizes eingeführt
- BFGs werden in dedizierten Elasticsearch-Cells mit einer Struktur aus mehreren Primary Shards verarbeitet
- Nach gleichzeitiger doppelter Indexierung in bestehende und neue Indizes wird das Query-Ziel schrittweise umgestellt
Ergebnisse
- Billionen von Nachrichten indexiert, bei doppelt so hohem Indexierungsdurchsatz wie zuvor
- Antwortzeit für Queries: im Durchschnitt 500 ms → 100 ms, p99 von 1 s → unter 500 ms
- Mehr als 40 Cluster und Tausende von Indizes im Betrieb
- Cluster-Upgrades und Rolling Restarts sind vollständig automatisiert und erfolgen ohne Service-Unterbrechung
4 Kommentare
Dass man so etwas auch noch im laufenden Betrieb betreibt … mein Respekt.
Das Discord-Engineering ist immer wieder vorbildlich. Ich bin neidisch.
Ich habe mich gefragt, was Pub/Sub ist, und offenbar ist es ein von GCP bereitgestelltes IaaS-Angebot.
https://cloud.google.com/pubsub?hl=en
Beeindruckend. Auch, dass sie zur Problemlösung alles umgekrempelt haben.