Fecha: 2020-03-03 Tiempo de lectura: 3 minutos Categoría: Operaciones Tags: mongodb / memoria / oom killer
Cuando tenemos un servidor mongodb en un entorno productivo solemos dedicar una máquina entera a la tarea, y no nos importa que consuma toda la memoria disponible. Sin embargo, en entornos de prueba o de preproducción solemos hacer convivir este servicio con otros procesos, y suelen tener conflictos de memoria.
Y es que si ponemos un servidor con mongodb, uno o más servidores de aplicaciones con varias aplicaciones y algún proceso auxiliar, el consumo de memoria se dispara; el resultado suele ser la caída de algún proceso cuando entra en funcionamiento el OOM Killer y empieza a matar procesos.
El asunto es que mongodb es una base de datos como todas las demás: intentará ocupar toda la memoria necesaria para cachear datos y tenerlos a mano para la siguiente vez que los pidan, con el fin de obtener un alto rendimiento. Sin embargo, en este tipo de entorno compartido, el rendimiento no es tan necesario, y el coste en máquinas es limitado…
La basta mayoría de la memoria que mongodb tiende a ocupar es por la caché de datos del disco. Asumiendo que estamos utilizando el storage engine WiredTiger, este valor se calcula desde las especificaciones de la máquina:
Starting in MongoDB 3.4, the default WiredTiger internal cache size is the larger of either:
* 50% of (RAM - 1 GB), or
* 256 MB.
Si no nos importa tener un rendimiento menor podemos dedicar menos tamaño a la
caché de disco modificando el parámetro de la configuración, que podemos
encontrar como storage.wiredTiger.engineConfig.cacheSizeGB
. Por supuesto, también
podemos incrementar el parámetro para dedicar más memoria y obtener un rendimiento
mayor en máquinas en las que nos lo podamos permitir.
Veamos un ejemplo; supongamos que tenemos dos servidores con mongodb:
Los valores por defecto serían los siguientes:
Sin embargo, dadas las circunstancias de nuestro entorno, esto no tiene sentido; el servidorA no necesita dejar memoria libre para ningún otro proceso, y el servidorB dejaría al resto de procesos con una memoria mínima.
Supongamos ahora que queremos limitar el servidorB a 512 MB; para ello necesitamos modificar su fichero de configuración para cambiar el parámetro antes mencionado:
gerard@servidorB:~$ cat /etc/mongod.conf
...
storage:
...
wiredTiger:
engineConfig:
cacheSizeGB: 0.5
...
gerard@servidorB:~$
Antes de aplicar los cambios, voy a verificar lo que hay, para poder comparar a posteriori:
gerard@servidorB:~$ echo "db.serverStatus()" | mongo | grep "maximum bytes configured"
"maximum bytes configured" : 1531969536,
gerard@servidorB:~$
Para aplicar este parámetro solo necesitamos reinciar el proceso mongod
, que
podemos hacer fácilmente delegando la operación en el gestor de procesos del sistema;
por estar en una máquina Debian 10, se trataría de SystemD.
gerard@servidorB:~$ sudo systemctl restart mongod
gerard@servidorB:~$
Y solo nos quedaría ver que el límite queda activado:
gerard@servidorB:~$ echo "db.serverStatus()" | mongo | grep "maximum bytes configured"
"maximum bytes configured" : 536870912,
gerard@servidorB:~$
Y con esto liberamos 1 GB de memoria para el uso de las aplicaciones que conviven en nuestro sobrecargado servidor. Si las aplicaciones están bien dimensionadas, no deberíamos volver a ver pasar a nuestro amigo el OOM Killer…