Hemos estado usando MongoDB durante varias semanas, la tendencia general que hemos visto es que mongodb está usando demasiada memoria (mucho más que el tamaño total de su conjunto de datos + índices).
Ya leí esta pregunta y esta pregunta , pero ninguna parece abordar el problema que he enfrentado, en realidad están explicando lo que ya se explicó en la documentación.
Los siguientes son los resultados de los comandos htop y show dbs .
Sé que mongodb usa IO mapeado en memoria, por lo que básicamente el sistema operativo maneja el almacenamiento en caché de las cosas en la memoria, y teóricamente, mongodb debería abandonar su memoria en caché cuando otro proceso solicita memoria libre , pero por lo que hemos visto, no lo hace.
OOM comienza a matar otros procesos importantes, por ejemplo, postgres, redis, etc. (Como se puede ver, para superar este problema, hemos aumentado la RAM a 183 GB, que ahora funciona pero es bastante costoso. Mongo está usando ~ 87 GB de ram, casi 4 veces el tamaño de todo su conjunto de datos)
Asi que,
- ¿Es este uso de memoria realmente esperado y normal? (Según la documentación, WiredTiger utiliza como máximo ~ 60% de RAM para su caché, pero teniendo en cuenta el tamaño del conjunto de datos, ¿tiene incluso suficientes datos para poder tomar 86 GB de RAM?)
- Incluso si se espera el uso de la memoria, ¿por qué Mongo no soltará su memoria asignada en caso de que otro proceso comience a solicitar más memoria? Linux oom estaba matando constantemente otros procesos en ejecución, incluido mongodb, antes de aumentar la RAM y hacer que el sistema fuera totalmente inestable.
Gracias !
fuente
Respuestas:
De acuerdo, después de seguir las pistas dadas por loicmathieu y jstell, y desenterrar un poco, estas son las cosas que descubrí sobre MongoDB usando el motor de almacenamiento WiredTiger. Lo pongo aquí si alguien encuentra las mismas preguntas.
Los subprocesos de uso de memoria que mencioné, todos pertenecían a 2012-2014, todos anteriores a WiredTiger y describen el comportamiento del motor de almacenamiento MMAPV1 original que no tiene un caché separado o soporte para la compresión.
La configuración de caché de WiredTiger solo controla el tamaño de la memoria directamente utilizada por el motor de almacenamiento WiredTiger (no la memoria total utilizada por mongod). Potencialmente, muchas otras cosas están tomando memoria en una configuración MongoDB / WiredTiger, como las siguientes:
WiredTiger comprime el almacenamiento en disco, pero los datos en la memoria no están comprimidos.
WiredTiger por defecto no sincroniza los datos en cada confirmación , por lo que los archivos de registro también están en la RAM, lo que afecta la memoria. También se menciona que para usar E / S de manera eficiente, WiredTiger agrupa las solicitudes de E / S (errores de caché) juntas, eso también parece tomar algo de RAM (de hecho, las páginas sucias (páginas que han cambiado / actualizado) tienen una lista de actualizaciones en ellos almacenados en una SkipList concurrente ).
WiredTiger mantiene múltiples versiones de registros en su caché (Control de concurrencia de versiones múltiples, las operaciones de lectura acceden a la última versión confirmada antes de su operación)
WiredTiger Mantiene sumas de verificación de los datos en caché.
MongoDB sí consume memoria para manejar las conexiones abiertas, agregaciones, código serverside y etc .
Teniendo en cuenta estos hechos, confiar en él
show dbs;
no era técnicamente correcto, ya que solo muestra el tamaño comprimido de los conjuntos de datos.Los siguientes comandos se pueden utilizar para obtener el tamaño completo del conjunto de datos.
Este resultado es el siguiente:
Por lo tanto, parece que el tamaño real del conjunto de datos + sus índices están tomando aproximadamente 68 GB de esa memoria.
Teniendo en cuenta todo esto, supongo que el uso de la memoria ahora es bastante esperado, buena parte es que está completamente bien limitar el tamaño de la caché WiredTiger, ya que maneja las operaciones de E / S de manera bastante eficiente (como se describió anteriormente).
También queda el problema de OOM, para superar este problema, ya que no teníamos suficientes recursos para eliminar mongodb, bajamos el oom_score_adj para evitar que OOM matara procesos importantes por el momento (lo que significa que le dijimos a OOM que no mate a nuestro procesos deseados ).
fuente
oom_score_adj
solución lo mejor que se te ocurrió?No creo que tenga un problema aquí con MongoDB, ya que jstell le dijo que MongoDB con WiredTiger usará el 50% de la memoria disponible, por lo que si aumenta la RAM de su servidor, necesitará más memoria.
Por qué es más grande que el tamaño de los índices DB +, tenga en cuenta que WiredTiger comprime la base de datos en el disco y también utiliza registros de instantáneas para registrar los cambios en el documento. Por lo tanto, el tamaño real de WiredTiger es el tamaño que usa show dbs * compress_ration + size de los registros de instantáneas. Por lo tanto, es casi imposible saber el tamaño exacto esperado.
También hay que tener en cuenta que las herramientas como
top
,ps
,htop
no mostrar la memoria realmente utilizada por la aplicación, refere a esta pregunta Declaración de trabajo para más detalles: https://stackoverflow.com/questions/131303/how-to-measure-actual-memory -uso-de-una-aplicación-o-procesoAhora, volviendo a su problema. Tiene otras herramientas ejecutándose en el mismo host y un OOM las mata. No estoy familiarizado con Linux OOM, pero ¿estás seguro de que los mata por MongoDB o ... solo por ellos (tal vez mata a Postgres porque Postgres tomó demasiada memoria)?
De todos modos, como práctica recomendada si tiene una gran base de datos Mongo, no la instale en un host compartido con otras bases de datos o tendrá muchas dificultades, en caso de que haya un problema como el que describe aquí, para saber quien realmente causa el problema en el host.
fuente
Docs
Es posible que desee leer las preocupaciones básicas de memoria para MongoDB y también esta breve discusión sobre cómo verificar el uso de la memoria .
Resumen de uso de memoria
El comando
db.serverStatus()
( docs ) puede proporcionar una descripción general del uso de la memoria, específicamente:¿Qué tan grandes son sus índices?
db.stats()
puede mostrar el tamaño total de todos los índices, pero también podemos obtener información detallada para una sola colección usandodb.myCollection.stats()
Por ejemplo, este comando comparará los tamaños de los índices para cada colección :
Ahora podemos ver los detalles de esa colección masiva, para ver cuáles de sus índices son los más costosos:
Esto nos puede dar una mejor idea de dónde podrían ser posibles los ahorros.
(En este caso, teníamos un índice sobre el
createTime
cual era bastante grande, una entrada por documento, y decidimos que podíamos vivir sin él).fuente
createTime
índice era problemático porque era único para cada documento y esa colección era enorme. La indexación de los otros campos estaba bien, porque había menos valores únicos (los valores estaban agrupados).