Wir verwenden MongoDB seit einigen Wochen. Der allgemeine Trend, den wir gesehen haben, war, dass Mongodb viel zu viel Speicher belegt (viel mehr als die gesamte Größe seines Datensatzes + der Indizes).
Ich habe diese Frage und diese Frage bereits durchgelesen , aber keine scheint sich mit dem Problem zu befassen, mit dem ich konfrontiert war. Sie erklären tatsächlich, was bereits in der Dokumentation erklärt wurde.
Das Folgende sind die Ergebnisse der Befehle htop und show dbs .
Ich weiß, dass mongodb speicherabgebildete E / A-Vorgänge verwendet, sodass das Betriebssystem im Grunde genommen das Zwischenspeichern von Dingen im Speicher handhabt, und mongodb sollte theoretisch seinen zwischengespeicherten Speicher freigeben, wenn ein anderer Prozess freien Speicher anfordert , was wir jedoch gesehen haben, ist dies nicht der Fall.
OOM startet damit, andere wichtige Prozesse wie Postgres, Redis usw. zu beenden. (Um dieses Problem zu beheben, haben wir den RAM auf 183 GB erhöht, was jetzt funktioniert, aber ziemlich teuer ist. Mongo verwendet ~ 87 GB RAM. fast 4X der Größe seines gesamten Datensatzes)
So,
- Ist so viel Speicherbedarf wirklich zu erwarten und normal? (Laut Dokumentation verwendet WiredTiger höchstens ~ 60% des Arbeitsspeichers für den Cache. Hat der WiredTiger unter Berücksichtigung der Datenmenge überhaupt genug Daten, um 86 GB RAM aufnehmen zu können?)
- Auch wenn die Speichernutzung erwartet wird, warum lässt mongo den zugewiesenen Speicher nicht los, falls ein anderer Prozess beginnt, mehr Speicher anzufordern? Verschiedene andere laufende Prozesse, einschließlich Mongodb selbst, wurden ständig von Linux-oom abgebrochen, bevor wir den Arbeitsspeicher vergrößerten und das System dadurch völlig instabil wurde.
Vielen Dank !
quelle
Antworten:
Okay, nachdem ich den Hinweisen von Loicmathieu und Jstell gefolgt und ein wenig nachgegangen bin, habe ich mithilfe der WiredTiger-Speicher-Engine Folgendes über MongoDB herausgefunden. Ich schreibe es hier, wenn jemand die gleichen Fragen hat.
Die Speicherauslastungsthreads, die ich erwähnt habe, gehörten alle zu 2012-2014, waren alle WiredTiger vor dem Datum und beschreiben das Verhalten der ursprünglichen MMAPV1-Speicher-Engine, die keinen separaten Cache oder keine Unterstützung für die Komprimierung hat.
Die WiredTiger- Cache-Einstellungen steuern nur die Größe des Speichers, der direkt von der WiredTiger-Speicher-Engine verwendet wird (nicht den von Mongod verwendeten Gesamtspeicher). In einer MongoDB / WiredTiger-Konfiguration beanspruchen möglicherweise viele andere Dinge Speicher, z. B. die folgenden:
WiredTiger komprimiert den Festplattenspeicher, die Daten im Speicher werden jedoch nicht komprimiert.
WiredTiger synchronisiert die Daten nicht standardmäßig bei jedem Commit , daher befinden sich die Protokolldateien auch im RAM, was den Arbeitsspeicher belastet . Es wird auch erwähnt, dass WiredTiger zur effizienten Nutzung von E / A-Vorgängen E / A-Anforderungen (Cache-Fehlschläge) zusammenfasst, was ebenfalls RAM-Speicher beansprucht auf ihnen in einer Concurrent SkipList gespeichert ).
WiredTiger speichert mehrere Versionen von Datensätzen im Cache (Multi Version Concurrency Control, Leseoperationen greifen auf die letzte festgeschriebene Version vor ihrer Operation zu).
WiredTiger Hält die Prüfsummen der Daten im Cache.
MongoDB selbst verbraucht Speicher, um offene Verbindungen, Aggregationen, serverseitigen Code usw. zu verarbeiten .
In Anbetracht dieser Tatsachen
show dbs;
war es technisch nicht korrekt , sich auf zu verlassen , da nur die komprimierte Größe der Datensätze angezeigt wird.Die folgenden Befehle können verwendet werden, um die vollständige Datenmenge abzurufen.
Dies führt zu folgenden Ergebnissen:
Es scheint also, dass die tatsächliche Datenmenge + ihre Indizes ungefähr 68 GB dieses Speichers beanspruchen.
In Anbetracht all dieser Faktoren ist die Speicherauslastung nun ziemlich hoch, und zum Teil ist es völlig in Ordnung, die Größe des WiredTiger-Caches zu begrenzen, da E / A-Vorgänge sehr effizient ausgeführt werden (wie oben beschrieben).
Es bleibt auch das Problem von OOM bestehen, um dieses Problem zu lösen, da wir nicht über genügend Ressourcen zum Entfernen von Mongodb verfügten. Daher haben wir oom_score_adj gesenkt , um zu verhindern, dass OOM wichtige Prozesse vorübergehend beendet gewünschte Prozesse ).
quelle
oom_score_adj
Lösung die beste Lösung, die Sie finden konnten?Ich glaube nicht, dass Sie hier ein Problem mit MongoDB haben, da laut Jstell MongoDB mit WiredTiger 50% des verfügbaren Arbeitsspeichers beansprucht. Wenn Sie also den Arbeitsspeicher Ihres Servers erhöhen, wird mehr Arbeitsspeicher benötigt.
Denken Sie daran, dass WiredTiger nicht nur die Größe von DB + -Indizes überschreitet, sondern auch die Datenbank auf der Festplatte komprimiert und Snapshot-Protokolle verwendet, um Dokumentänderungen aufzuzeichnen. Die tatsächliche Größe des WiredTigers entspricht also der Größe, die unter Verwendung von show dbs * compression_ration + Größe der Snapshot-Protokolle ermittelt wurde. So ist es fast unmöglich, die genaue erwartete Größe zu kennen.
Denken Sie auch daran , dass Werkzeuge wie
top
,ps
,htop
hat die Erinnerung nicht angezeigt werden wirklich von der Anwendung verwendet, refere auf diese SOW Frage nach Details: https://stackoverflow.com/questions/131303/how-to-measure-actual-memory -gebrauch-einer-anwendung-oder-prozessNun zurück zu Ihrem Problem. Sie haben andere Tools, die auf demselben Host ausgeführt werden, und ein OOM beendet sie. Ich bin nicht mit Linux OOM vertraut, aber sind Sie sicher, dass es diese wegen MongoDB oder .. nur wegen ihnen tötet (vielleicht tötet es Postgres, weil Postgres zu viel Speicherplatz in Anspruch genommen hat).
Wie auch immer, als Best Practice, wenn Sie eine große Mongo-Datenbank haben, installieren Sie sie nicht auf einem Host, der mit anderen Datenbanken geteilt wird, oder Sie werden eine Menge Schwierigkeiten haben, falls es ein Problem wie das hier beschriebene gibt die wirklich das Problem auf dem Host verursachen.
quelle
Docs
Sie möchten vielleicht grundlegende Speicherprobleme für MongoDB und auch diese kurze Diskussion über das Überprüfen der Speichernutzung lesen .
Übersicht über die Speichernutzung
Der Befehl
db.serverStatus()
( docs ) bietet einen Überblick über die Speichernutzung, insbesondere:Wie groß sind Ihre Indizes?
db.stats()
kann die Gesamtgröße aller Indizes anzeigen, aber wir können mit auch detaillierte Informationen für eine einzelne Sammlung abrufendb.myCollection.stats()
Mit diesem Befehl werden beispielsweise die Größen der Indizes für jede Sammlung verglichen :
Jetzt können wir uns die Details für diese umfangreiche Sammlung ansehen , um herauszufinden, welche ihrer Indizes die teuersten sind:
Dies kann uns eine bessere Vorstellung davon geben, wo Einsparungen möglich sind.
(In diesem Fall hatten wir einen Index,
createTime
der ziemlich umfangreich war - ein Eintrag pro Dokument - und wir entschieden, dass wir ohne ihn leben könnten.)quelle
createTime
Index problematisch, da er für jedes einzelne Dokument eindeutig war und diese Sammlung riesig war. Das Indizieren der anderen Felder war in Ordnung, da weniger eindeutige Werte vorhanden waren (die Werte wurden in Clustern zusammengefasst).