Best Practices zur Optimierung der Leseleistung in Replica Sets
Verbessern Sie MongoDB-Replica-Set-Lesevorgänge mit Read Preference, Read Concern, Lag-Überwachung, Indizierung und Timeout-Steuerung.
Best Practices zur Optimierung der Leseleistung in Replica Sets
MongoDB-Replica-Sets bieten Hochverfügbarkeit, aber sie beschleunigen Lesevorgänge nicht automatisch. Wenn Ihre Anwendung jede Abfrage an das Primary sendet, schwache Indizes verwendet oder von nachlaufenden Secondaries liest, werden Benutzer dies als langsame Seiten und veraltete Daten spüren.
Eine gute Leseleistung ergibt sich aus der Wahl der richtigen Read Preference, der Abstimmung des Read Concern auf die benötigte Konsistenz, der Überwachung der Replikationsverzögerung und der Behebung langsamer Abfragen zuerst.
Verstehen des Lesepfads in Replica Sets
In einer Standard-Replica-Set-Bereitstellung wird ein Mitglied als Primary bezeichnet und bearbeitet alle Schreibvorgänge. Die übrigen Mitglieder sind Secondaries, die die Daten asynchron vom Primary replizieren. Anwendungslesevorgänge können je nach Konfiguration an das Primary oder auf die Secondaries verteilt werden.
Die Optimierung von Lesevorgängen bedeutet, die Notwendigkeit sofortiger Datenkonsistenz (die oft das Lesen vom Primary erfordert) gegen den Wunsch abzuwägen, Traffic vom Primary zu entlasten (durch Lesen von Secondaries).
1. Strategischer Einsatz von Read Concerns
Read Concern definiert den Grad der Datenkonsistenz, der für Leseoperationen erforderlich ist. Das Setzen eines zu strengen Read Concerns, wenn ein lockerer ausreicht, ist eine häufige Ursache für Lese-Latenz, da es die Operation zwingen kann, auf Bestätigungen von mehreren Knoten zu warten.
Verfügbare Read Concerns
MongoDB bietet mehrere Read Concerns, die jeweils Latenz gegen Haltbarkeit/Konsistenz abwägen:
| Read Concern | Beschreibung | Anwendungsfall |
|---|---|---|
majority |
Gibt Daten zurück, die von einer Mehrheit der stimmberechtigten Knoten als committet bestätigt wurden. Standardeinstellung. | Allgemeine Lesevorgänge, die hohe Haltbarkeit erfordern. |
local |
Gibt die aktuellsten Daten zurück, die auf dem gelesenen Mitglied verfügbar sind, unabhängig von der Schreibbestätigung. | Lesevorgänge, die etwas veraltete Daten tolerieren können (z. B. Dashboard-Zähler). |
linearizable |
Liest vom Primary und spiegelt alle Schreibvorgänge wider, die vor Beginn des Lesevorgangs bestätigt wurden. Erfordert readConcern: "linearizable" und Majority Write Concern für die betreffenden Schreibvorgänge. |
Seltene Lesevorgänge, die den neuesten bestätigten Zustand beobachten müssen, wie z. B. Lock-Besitzprüfungen. |
Optimierungstipp: Standardmäßig local oder majority verwenden
Verwenden Sie für nicht kritische Lesevorgänge (wie das Laden von selten aktualisierten Konfigurationsdaten oder zwischengespeicherten Ergebnissen) den local Read Concern auf Secondaries. Dies vermeidet jegliche Synchronisationsverzögerung.
Beispiel: Setzen des Read Concerns auf Sitzungsebene
// Setzen des Read Concerns auf 'local' für diese spezifische Sitzung
const session = mongoClient.startSession({ readConcern: { level: "local" } });
// Find-Operation mit der Sitzung
db.collection('mydata').find().session(session).toArray();
Warnung: Das Lesen mit
localConcern auf einem Secondary kann veraltete Daten relativ zum Primary zurückgeben.
2. Verteilen von Lesevorgängen auf Secondaries
Standardmäßig leitet MongoDB Lesevorgänge an das Primary. Um die Lesekapazität zu skalieren, müssen Sie Lesevorgänge explizit mit Read Preference-Einstellungen an Secondaries weiterleiten.
Read Preference verstehen
Read Preference bestimmt, welche Mitglieder des Replica Sets für die Erfüllung von Leseanfragen in Frage kommen und in welcher Reihenfolge sie ausgewählt werden sollen.
Häufige Read Preferences umfassen:
primary: (Standard) Nur das Primary ist berechtigt.primaryPreferred: Versucht zuerst das Primary; fällt auf ein Secondary zurück, wenn das Primary nicht verfügbar ist.secondary: Nur Secondaries sind berechtigt. Wenn keine Secondaries verfügbar sind, schlägt die Operation fehl.secondaryPreferred: Bevorzugt Secondaries; fällt auf das Primary zurück, wenn keine Secondaries verfügbar sind.nearest: Wählt das Mitglied (Primary oder Secondary) mit der geringsten Netzwerklatenz zum Client aus.
Optimierungstipp: Verwendung von secondaryPreferred oder nearest
Verwenden Sie für die meisten leseintensiven Anwendungen secondaryPreferred, um die Abfragelast auf alle verfügbaren Secondaries zu verteilen und die Last auf dem Primary erheblich zu reduzieren.
Wenn Sie geografisch verteilte Anwendungsserver haben, ist nearest oft die beste Wahl, da es die Netzwerklatenz für den Client minimiert, auch wenn es gelegentlich das Primary trifft.
Beispiel: Verbinden mit secondaryPreferred
Geben Sie beim Verbinden Ihres Anwendungstreibers die Read Preference an:
const uri = "mongodb://host1,host2,host3/?replicaSet=rs0&readPreference=secondaryPreferred";
// Oder mit Verbindungsoptionen in einem Treiber-Setup
const options = {
readPreference: "secondaryPreferred"
};
3. Verwalten der Secondary-Synchronisation und -Verzögerung
Wenn Sie Lesevorgänge an Secondaries weiterleiten, hängt die Leistung dieser Lesevorgänge vollständig davon ab, wie schnell die Secondaries mit dem Primary Schritt halten. Eine hohe Replikationsverzögerung bedeutet, dass Secondaries veraltete Daten ausliefern, oder wenn die Verzögerung zu hoch ist, können Lesevorgänge fehlschlagen oder ein Timeout auftreten.
Überwachung der Replikationsverzögerung
Überwachen Sie immer den Optime-Unterschied zwischen dem Primary und den Secondaries. rs.status() zeigt den Replikationsstatus pro Mitglied, und verwaltete Tools wie MongoDB Atlas, Cloud Manager oder Ops Manager können bei Verzögerungen alarmieren.
rs.status().members.map(m => ({
name: m.name,
stateStr: m.stateStr,
optimeDate: m.optimeDate
}))
Auswirkungen des Write Concerns auf die Secondary-Leistung
Obwohl sich dieser Artikel auf Lesevorgänge konzentriert, können hohe Write Concern-Einstellungen die Leseleistung indirekt beeinträchtigen, indem sie das Primary verlangsamen, was wiederum dazu führt, dass Secondaries weiter zurückfallen.
Zum Beispiel bedeutet die Anforderung von w: "majority", dass der Client keine Bestätigung erhält, bis der Schreibvorgang eine Mehrheit der stimmberechtigten datentragenden Mitglieder erreicht hat. Wenn Secondaries aufgrund von Festplatten- oder Netzwerkdruck langsam sind, kann die Anwendungsschreib-Latenz steigen, und dieselben überlasteten Secondaries können auch langsame Lesevorgänge bedienen.
Best Practice für Write Concern (Indirekte Leseoptimierung): Senken Sie den Write Concern nicht nur, um Lesevorgänge schneller erscheinen zu lassen. Wählen Sie den Write Concern basierend auf den Haltbarkeitsanforderungen und beheben Sie dann die Ursache der Verzögerung: langsame Festplatten, überlastete Secondaries, zu kleine Oplog, Netzwerkprobleme oder Abfragen, die mit der Replikation konkurrieren.
4. Indizierung und Abfrageoptimierung
Keine Konfigurationseinstellung kann eine schlecht geschriebene Abfrage überwinden. Das grundlegende Prinzip schneller Lesevorgänge bleibt eine robuste Indizierung.
Wichtige Überlegungen zur Indizierung
- Covered Queries: Entwerfen Sie Abfragen, die vollständig durch einen Index erfüllt werden können, ohne Dokumente von der Festplatte abzurufen. Dies sind die schnellstmöglichen Lesevorgänge.
- Index-Ausrichtung: Stellen Sie sicher, dass Indizes mit den Feldern übereinstimmen, die in Ihren
find(),sort()undprojection()-Klauseln verwendet werden. - Vermeiden Sie Collection-Scans: Überprüfen Sie immer im Query Profiler, dass Leseoperationen Indizes (
IXSCAN) verwenden, anstatt vollständige Collection-Scans (COLLSCAN) durchzuführen.
Optimierung von Abfrage-Timeouts
Wenn eine Anwendung auf ein stark nachlaufendes Secondary trifft, kann die Abfrage ein Timeout verursachen. Konfigurieren Sie angemessene Timeouts in Ihrer Anwendung, um vorübergehende Verzögerungen elegant zu handhaben, indem Sie möglicherweise auf das Primary zurückfallen oder später erneut versuchen, anstatt unbegrenzt zu hängen.
Zusammenfassung der Schritte zur Leseoptimierung
Um eine optimale Leseleistung in Ihrem MongoDB-Replica-Set zu erreichen, befolgen Sie diese umsetzbaren Schritte:
- Lesetypen identifizieren: Klassifizieren Sie Lesevorgänge in solche, die frische Primary-Daten benötigen, und solche, die eventuelle Konsistenz von Secondaries tolerieren können.
- Read Preference konfigurieren: Setzen Sie die Verbindungszeichenfolge oder Sitzungsoptionen, um für den Großteil des Anwendungsverkehrs
secondaryPreferredodernearestzu verwenden. - Verzögerung überwachen: Überwachen Sie kontinuierlich die Replikationsverzögerung mit
rs.status(), Treibermetriken oder Ihrer Überwachungsplattform. Wenn die Verzögerung konstant hoch ist, untersuchen Sie Probleme mit der Secondary-Hardware oder dem Netzwerk. - Write Concerns überprüfen: Stellen Sie sicher, dass Write Concerns das Primary nicht unnötig verlangsamen, was Secondaries von frischen Daten abschneidet.
- Gründlich indizieren: Überprüfen Sie, dass alle häufig ausgeführten Lesepfade effiziente Indizes verwenden.
Die Skalierung von Lesevorgängen in Replica Sets funktioniert am besten, wenn Sie ehrlich bezüglich der Datenaktualität sind. Senden Sie benutzerkritische Lesevorgänge an das Primary, wenn sie aktuell sein müssen, verwenden Sie Secondaries für Analysen oder Dashboards, die Verzögerungen tolerieren können, und messen Sie weiterhin Abfragepläne und Replikationszustand, während sich der Traffic ändert.