Habilidades prácticas para mejorar la eficiencia de la operación y el mantenimiento de MongoDB

1. Introducción al Clúster MongoDB

MongoDB es una base de datos basada en almacenamiento de archivos distribuidos, que tiene como objetivo proporcionar soluciones escalables de almacenamiento de datos de alto rendimiento para aplicaciones WEB. La solución de clúster más común se presentará a continuación con 3 máquinas. Para una introducción detallada, puede ver el sitio web oficial https://docs.mongodb.com/v3.4/introduction/.

1. Introducción a los componentes del clúster

  • mongos (procesamiento de enrutamiento): como la entrada de solicitud del clúster Cliente y MongoDB, todas las solicitudes de los usuarios se coordinarán a través de Mongos, que enviará la solicitud de datos al servidor Shard (mongod) correspondiente, y luego fusionará los datos y los enviará de vuelta a el usuario.

  • servidor de configuración (nodo de configuración): a saber: servidor de configuración; principalmente guarda los metadatos de la base de datos, incluida la distribución de datos (fragmentación) y la estructura de datos. Después de recibir la solicitud del cliente, mongos cargará la información de configuración del servidor de configuración y el caché en la memoria. Generalmente, se configurará más de un servidor de configuración en el entorno de producción, porque los metadatos que guarda son extremadamente importantes y, si se dañan, afectarán el funcionamiento de todo el clúster.

  • Fragmento (la instancia de fragmento almacena datos): un fragmento es un fragmento. MongoDB utiliza el mecanismo de fragmentación para realizar el almacenamiento y procesamiento de la distribución de datos y lograr el propósito de la expansión horizontal. De forma predeterminada, los datos se transferirán automáticamente entre fragmentos para lograr el equilibrio. Esta acción se logra mediante un mecanismo llamado equilibrador.

  • Conjunto de réplicas (réplica set): El conjunto de réplicas se da cuenta de la alta disponibilidad de la base de datos. Si no se realiza el conjunto de réplicas, una vez que el nodo del servidor que almacena los datos cuelga, los datos se perderán. Por el contrario, si el conjunto de réplicas está configurado, los mismos datos se guardarán en En el servidor de réplica (nodo de réplica), el conjunto de réplica general incluye un nodo maestro y varios nodos de réplica. Si es necesario, un árbitro (nodo de arbitraje) se configurará como un nodo de votación cuando el el nodo cuelga.

  • Árbitro (nodo de arbitraje): el servidor de arbitraje en sí no contiene datos. Solo puede detectar todos los servidores de réplica y elegir un nuevo nodo maestro cuando el nodo principal falla. Esto se logra a través del latido entre el nodo maestro, el nodo de réplica y el arbitraje. servidor (latido del corazón) se dio cuenta.

2. Escenarios de aplicación de MongoDB

  • Datos del sitio web: adecuado para la inserción, actualización y consulta en tiempo real, y tiene la replicación y la alta escalabilidad necesarias para el almacenamiento de datos en tiempo real en el sitio web.

  • Caché: Por su alto rendimiento, también es adecuado como capa de caché para infraestructuras de información. Una vez que se reinicia el sistema, la memoria caché persistente creada puede evitar que se sobrecargue la fuente de datos subyacente.

  • Datos de gran tamaño y bajo valor: puede ser más costoso almacenar algunos datos utilizando bases de datos relacionales tradicionales.Antes de eso, muchos programadores suelen elegir archivos tradicionales para el almacenamiento.

  • Escenarios de alta escalabilidad: muy adecuado para bases de datos formadas por decenas o cientos de servidores.

  • Se utiliza para el almacenamiento de datos de objetos y JSON: el formato de datos BSON de MongoDB es muy adecuado para el almacenamiento y la consulta con formato de documentos.

3. Razones para elegir MongoDB

Los datos seleccionados por MongoDB están en formato de datos BSON, que es altamente escalable y fácil de expandir, y la expansión horizontal de los datos es muy simple, admite el almacenamiento masivo de datos y tiene un rendimiento poderoso.

2. Monitoreo de clústeres

1. Base de datos de seguimiento para almacenar información estadística

Ingrese la instancia de mongos o fragmento en la ventana acoplable y ejecute el siguiente comando:

docker exec -it mongos bash;
mongo --port 20001;
use admin;
db.auth("root","XXX");

Descripción: a través de este comando, puede consultar datos relacionados, como la cantidad de colecciones y la cantidad de índices de los miembros del clúster.

db.stats();

2. Ver las estadísticas de la base de datos

Descripción: a través de este comando, puede ver la cantidad de operaciones, el uso de memoria, la red io, etc.

db.runCommand( { serverStatus: 1 } );

3. Comprobar el estado de los miembros del conjunto de réplicas

rs.status();

3. Operaciones básicas de operación y mantenimiento

1. Establecer y ver consultas lentas

# 设置慢查询
db.setProfilingLevel(1,200);
# 查看慢查询级别
db.getProfilingLevel();
# 查询慢查询日志,此命令是针对于某一库进行设置
db.system.profile.find({ ns : 'dbName.collectionName'}).limit(10).sort( { ts : -1 } ).pretty();

2. Ver acciones que tardan mucho tiempo en ejecutarse

db.currentOp({"active" : true,"secs_running" : { "$gt" : 2000 }});

3. Ajuste dinámicamente el nivel de registro y establezca el tamaño de caché

# 设置日志级别参数
db.adminCommand( { "getParameter": 1, "logLevel":1});
# 设置cache大小参数
db.adminCommand( { "setParameter": 1, "wiredTigerEngineRuntimeConfig": "cache_size=4G"});

4. Agregar y eliminar miembros del conjunto de réplicas

# 查看复制集成员
rs.status().members;
# 添加成员
rs.add('127.0.0.1:20001');
# 移除成员
rs.remove('127.0.0.1:20001');

5. Configurar la base de datos y la fragmentación de colecciones

# 在mongos admin库设置库允许分片
sh.enableSharding("dbName");
# 在mongos 的admin库设置集合分片片键
sh.shardCollection("dbName.collectionName", { filedName: 1} );

6. Agregar y eliminar fragmentos

# 查看分片状态
sh.status();
# 在mongos执行添加分片(可以为单个实例或复制集)
db.runCommand( { removeShard: "shardName" } );
db.runCommand({addshard:"rs1/ip-1:20001,ip-2:20001,ip-3:20001"});
# 在mongos执行移除分片
db.runCommand( { removeShard: "shard3" } );
# 在mongos执行刷新mongos配置信息
db.runCommand("flushRouterConfig"));

Nota : El comando para eliminar un fragmento se debe ejecutar al menos dos veces antes de que se pueda eliminar correctamente. No se eliminará hasta que se complete el estado. De lo contrario, el fragmento se eliminará correctamente. El fragmento se encuentra en el estado. {"draining" : true}También afecta la eliminación posterior de otros fragmentos. Puede ejecutarlo nuevamente cuando encuentre este estado. removeshardEs mejor ejecutar repetidamente el comando de eliminación hasta que se complete el estado; hay otro punto que necesita atención: se eliminó con éxito. Si lo desea para volver a unirse al clúster, debe limpiar el directorio de datos antes de volver a unirse al clúster. De lo contrario, incluso si puede unirse con éxito, los datos no se almacenarán y la colección no se creará. Además: al eliminar un fragmento , hay Puede haber un estado infinito en todo el proceso {"draining" : true}, y seguirá siendo el mismo después de mucho tiempo, y ninguno de los bloques en el fragmento se ha movido a otros fragmentos. La solución es: encontrar la información del shard en la colección de fragmentos de la base de datos de configuración en config, y configure El campo de drenaje se cambia de Verdadero a Falso, y luego continúe intentando eliminar". La oración anterior regresará de inmediato, y en realidad se ejecutará en segundo plano. Durante el proceso de eliminación de datos, debe prestar atención a la información de registro de la instancia, y es posible que haya bloques de datos en el proceso de migración. Sin embargo, no se puede encontrar la condición límite, lo que conduce a la falla de la migración de datos y al reintento. La solución es eliminar los datos del límite y reiniciar la instancia. Si el fragmento es el fragmento principal, primero se debe migrar el fragmento principal. Después de la eliminación Después de eso, ejecute el db.runCommand( { movePrimary: "XXX", to: "other" });siguiente comando en todos los mongos y luego proporcione servicios externos, por supuesto, también puede reiniciar todas las instancias de mongos.

7. Importación y exportación de datos

# 导出允许指定导出条件和字段
mongoexport -h 127.0.0.1 --port 20001 -uxxx -pxxx -d xxx -c mobileIndex -o XXX.txt 
mongoimport -h 127.0.0.1 --port 20001 -uxxx -pxxx -d xxx -c mobileIndex --file XXX.txt

4. Migración de datos MongoDB

1. Migrar miembros en el conjunto de réplicas

  • Cierre la instancia de mongod, para garantizar un apagado seguro, use el comando de apagado;

  • Transfiera el directorio de datos (es decir, dbPath) a la nueva máquina;

  • Inicie mongod en la nueva máquina, donde el directorio de datos del nodo es el directorio de archivos de la copia;

  • Conéctese al nodo principal actual del conjunto de réplicas;

Si la dirección del nuevo nodo cambia, use rs.reconfig() para actualizar el archivo de configuración del conjunto de réplicas, por ejemplo, el siguiente proceso de comando actualizará la segunda dirección del miembro:

cfg = rs.conf()
cfg.members[2].host = "127.0.0.1:27017"
rs.reconfig(cfg)

Utilícelo  rs.conf() para confirmar que se utiliza la nueva configuración. Espere a que todos los miembros vuelvan a la normalidad y utilícelo para  rs.status() detectar el estado de los miembros.

2. Migre el nodo principal del conjunto de réplicas

Al migrar el nodo principal, se requiere que el conjunto de réplicas elija un nuevo nodo principal. Durante la elección, el conjunto de réplicas leerá y escribirá. Por lo general, esto durará poco tiempo, pero debe ser lo más pequeño posible. El nodo principal se migra dentro del período de tiempo.

  • Degradar el nodo maestro, para que comience la conmutación por error normal. Para degradar el nodo maestro, conéctese a un nodo maestro, use el  replSetStepDownmétodo o use rs.stepDown()el método, el siguiente ejemplo usa  rs.stepDown()el método para degradar:

rs.stepDown()
  • Después de que el nodo maestro se degrada a un nodo esclavo y otro miembro se convierte en miembro  PRIMARY , el nodo degradado se puede migrar de acuerdo con "Migrar un miembro del conjunto de réplicas". Se puede usar  rs.status()para confirmar el cambio de estado.

3. Restaurar datos de otros nodos en el conjunto de réplicas

MongoDB puede garantizar un almacenamiento de datos altamente confiable a través del conjunto de réplicas. Generalmente, se recomienda usar un "conjunto de réplicas de 3 nodos" en el entorno de producción, de modo que incluso si uno de los nodos falla y no se puede iniciar, podemos borrarlo directamente. datos Después de reiniciar, podemos usar el nuevo El nodo secundario se une al conjunto de replicación, o copia los datos de otros nodos, reinicia el nodo y sincronizará automáticamente los datos, logrando así el propósito de la recuperación de datos.

  • Apague el nodo que necesita sincronización de datos

docker stop node;  # docker环境中
db.shutdownServer({timeoutSecs: 60}); # 非docker环境
  • Copie el directorio de almacenamiento de datos (/dbPath) de la máquina del nodo de destino en el directorio especificado de la máquina actual.

scp 目标节点 shard/data -> 当前节点 shard/data
  • El nodo actual inicia el nodo con el archivo de datos copiado

  • Agregar nuevos nodos al conjunto de réplicas

# 进入复制集的主节点,执行添加新的节点命令
rs.add("hostNameNew:portNew"); 
# 等待所有成员恢复正常,检测成员状态
rs.status();
# 移除原来的节点
rs.remove("hostNameOld>:portOld"); 

Cinco, solución de escenario de problema en línea de MongoDB

1. MongoDB crea un nuevo índice que hace que la biblioteca se bloquee

Descripción del problema : para optimizar el negocio de una colección en línea de decenas de millones, el comando para crear un nuevo índice se ejecuta directamente, lo que provoca que toda la biblioteca se bloquee y el servicio de la aplicación no esté disponible.

Solución : Descubra el proceso de operación y elimínelo. Al cambiar para crear un nuevo índice en segundo plano, la velocidad será muy lenta, pero no afectará el negocio. El índice solo tendrá efecto después de que se complete la nueva creación;

# 查询运行时间超过200ms操作     
db.currentOp({"active" : true,"secs_running" : { "$gt" : 2000 }}) ;
# 杀死执行时间过长操作操作
db.killOp(opid)
# 后台新建索引
db.collectionNmae.ensureIndex({filedName:1}, {background:true});

2. MongoDB no limita la memoria, lo que hace que la instancia se cierre

Descripción del problema : cierta máquina en el entorno de producción inicia varias instancias de mongod y, después de ejecutarse durante un período de tiempo, el proceso se interrumpe inexplicablemente;

Solución : ahora MongoDB usa WiredTiger como el motor de almacenamiento predeterminado, y MongoDB usa tanto el caché interno de WiredTiger como el caché del sistema de archivos. Desde 3.4, la memoria caché interna de WiredTiger usa por defecto la más grande: 50 % (RAM - 1 GB) o 256 MB. Por ejemplo, en un sistema con un total de 4 GB de RAM, la caché de WiredTiger utilizará 1,5 GB de RAM(). Por el contrario, un sistema con un total de 1,25 GB de RAM asignará 256 MB para el caché de WiredTiger, ya que esto es más de la mitad del total de RAM menos 1 gigabyte ( ). 0,5 * (4 GB - 1 GB) = 1,5 GB``0,5 * (1,25 GB - 1 GB) = 128 MB < 256 MB. Si hay varias instancias de una máquina, el sistema operativo eliminará algunos procesos en caso de memoria insuficiente;

# 要调整WiredTiger内部缓存的大小,调节cache规模不需要重启服务,我们可以动态调整:
db.adminCommand( { "setParameter": 1, "wiredTigerEngineRuntimeConfig": "cache_size=xxG"})

3. MongoDB elimina datos sin liberar espacio en disco

Descripción del problema : en el escenario de eliminar una gran cantidad de datos (la cantidad de datos que manejo es de más de 20 millones) y el volumen de solicitudes es grande en el entorno de producción, la carga de la CPU de la máquina parecerá muy alta en este momento. tiempo, y la máquina puede incluso congelarse y no puede ser operada. Tales operaciones deben dividirse cuidadosamente en lotes; después de ejecutar el comando de eliminación, se encuentra que el tamaño de datos del disco no ha cambiado.

solución:

  • Solución 1 : Podemos usar la función de reducción de datos en línea proporcionada por MongoDB db.collectionName.runCommand("compact")para realizar una reducción de datos a nivel de colección a través del comando Compact y eliminar los fragmentos de archivo donde se encuentra la colección. Este comando es para proporcionar una contracción en línea y la contracción afectará los servicios en línea al mismo tiempo. Para resolver este problema, primero puede ejecutar el comando de desfragmentación del disco en el nodo esclavo. Una vez completada la operación, cambie el nodo maestro para cambiar el nodo maestro original a un nodo esclavo y ejecute el comando Compact nuevamente.

  • Solución 2 : utilice la resincronización del nodo esclavo, la resincronización del nodo secundario, elimine los datos especificados en el nodo secundario y reinicie la sincronización de datos con el nodo principal. La resincronización también se puede utilizar cuando los datos del miembro del conjunto de réplicas son demasiado antiguos. La resincronización de datos es diferente de la copia directa de archivos de datos.MongoDB solo sincroniza datos, por lo que no hay una colección vacía de archivos de datos después de que se completa la resincronización, lo que permite recuperar el espacio en disco.

    Para algunos casos especiales, si el nodo secundario no puede estar fuera de línea, puede agregar un nodo al conjunto de réplicas y luego el nodo secundario comenzará automáticamente la sincronización de datos. En términos generales, el método de resincronización es mejor. Primero, básicamente no bloqueará la lectura y escritura del conjunto de réplicas. Segundo, el tiempo consumido es relativamente más corto que los dos primeros.

    1. Si es un nodo principal, oblíguelo a convertirse primero en un nodo secundario; de lo contrario, omita este paso:rs.stepdown(120);

    2. Luego elimine el nodo secundario en el principal:rs.remove("IP:port");

    3. Eliminar todos los archivos bajo el dbpath del nodo secundario

    4. Vuelva a unir el nodo al clúster y luego haga que sincronice automáticamente los datos:rs.add("IP:port");

    5. Una vez completada la sincronización de datos, los pasos del ciclo 1-4 pueden liberar el espacio en disco de todos los nodos del clúster.

4. La carga de la máquina MongoDB es extremadamente alta

Descripción del problema : este escenario se basa en una gran solicitud de un cliente. Dado que la máquina donde se implementa MongoDB contiene un maestro y un esclavo, MongoDB hace IO100%, la base de datos se bloquea y aparece una gran cantidad de consultas lentas, lo que lleva a una carga de máquina extremadamente alta y servicios de aplicación completamente no disponibles.

Solución : en ausencia de una expansión oportuna de la máquina, la primera tarea es reducir el IO de la máquina.Cuando una máquina tiene un maestro y un esclavo, y cuando se escribe una gran cantidad de datos, aprovechará los recursos de IO de entre sí. Entonces, en este momento, se abandona la función de alta disponibilidad de MongoDB y se eliminan los nodos esclavos en el conjunto de réplicas para garantizar que solo un nodo de cada máquina pueda ocupar recursos de disco. Después de eso, la carga en la máquina disminuyó inmediatamente y el servicio volvió a estar disponible normalmente. Sin embargo, MongoDB no puede garantizar la integridad de los datos en este momento. Una vez que el nodo maestro cuelga, los datos se perderán. Esta solución es solo una solución temporal. La solución fundamental es aumentar la memoria de la máquina, usar una unidad de estado sólido o aumentar el conjunto de fragmentación para reducir la presión de lectura y escritura de una sola máquina.

# 进入主节点,执行移除成员的命令
rs.remove("127.0.0.1:20001");
# 注意:切勿直接关停实例

5. La selección incorrecta de la clave de fragmento de MongoDB conduce a la lectura y escritura en caliente

Descripción del problema : en el entorno de producción, la clave de fragmento de una determinada colección utiliza un método similar al método de generación de _id, y el campo que contiene la serie temporal se utiliza como clave de fragmento ascendente, lo que hace que los datos se escriban en un bloque de datos A medida que aumenta la cantidad de datos, hará que los datos se migren a la partición anterior, lo que provocará la ocupación de los recursos del sistema y consultas lentas ocasionales.

Solución : la solución temporal establece la ventana para la migración de datos, que se coloca en el período de tiempo normal, lo que afectará el negocio. La solución fundamental es reemplazar la clave de fragmento.

# 连接mongos实例,执行以下命令
db.settings.update({ _id : "balancer" }, { $set : { activeWindow : { start : "23:00", stop : "4:00" } } }, true );
# 查看均衡窗口
sh.getBalancerWindow();

6. Sugerencias de optimización de MongoDB

1. Optimización del nivel de aplicación

Optimización de consultas : confirme si su consulta utiliza completamente el índice, use el comando de explicación para verificar la ejecución de la consulta, agregue los índices necesarios y evite las operaciones de escaneo de tablas.

Diseño razonable de clave de fragmentación : clave de fragmentación incremental: adecuada para campos que se pueden dividir en rangos, como tipos enteros, flotantes y de fecha, y la consulta es más rápida. Random sharding-key: Es adecuado para escenarios con operaciones de escritura frecuentes, en este caso, si se realiza en un fragmento, la carga de este fragmento será mayor que la de otros fragmentos, lo que no está lo suficientemente equilibrado. Se espera que las claves de consulta hash se puedan usar para distribuir escrituras en múltiples fragmentos. Lleve a cabo lo anterior, considere la clave compuesta como la clave de fragmentación, el principio general es consultar rápido, minimizar las consultas entre fragmentos y la cantidad de saldos de saldo es pequeño; una sola clave de fragmentación incremental puede hacer que todos los datos escritos estén en la última parte, y la última parte de la presión de escritura aumenta, la cantidad de datos aumenta, hará que los datos migren a la partición anterior. MongoDB tiene por defecto un único registro de 16M, especialmente cuando se usa GFS, debe prestar atención al diseño de la clave de fragmentación. Aparecerá una clave de fragmentación irrazonable y varios documentos se almacenan en un solo fragmento. Al mismo tiempo, debido a que GFS a menudo almacena archivos grandes, MongoDB no puede usar la clave de fragmentación para separar estos documentos múltiples al hacer el balance. A diferentes fragmentos, en este momento MongoDB continuará informando errores y, finalmente, conducirá a la caída de MongoDB. Solución: aumente el tamaño de los fragmentos (solucione los síntomas) y diseñe una clave de fragmentación razonable (solucione la causa raíz).

Supervise los datos a través del perfil : realice la optimización para verificar si la función de perfil está actualmente habilitada y use el comando db.getProfilingLevel() para devolver el nivel de nivel. El valor es 0|1|2, que representan significados respectivamente: 0 significa apagado, 1 significa grabar comandos lentos , y 2 significa todo. El comando para habilitar la función de perfil es  db.setProfilingLevel(level); #level. Cuando el nivel de valor es 1, el valor predeterminado del comando lento es 100 ms. Si se cambia a db.setProfilingLevel(level,slowms)如db.setProfilingLevel(1,50)esto, se cambiará a 50 ms al db.system.profile.find() ver el registro de monitoreo actual.

2. Optimización del nivel de hardware

2.1 Determine el tamaño de los datos calientes: su conjunto de datos puede ser muy grande, pero esto no es tan importante. Lo que importa es qué tan grande es su conjunto de datos calientes y qué tamaño tienen los datos de acceso frecuente (incluidos los datos de acceso frecuente y todos los datos de índice). ) . Al usar MongoDB, es mejor que se asegure de que sus datos activos estén por debajo del tamaño de la memoria de su máquina y de que la memoria pueda acomodar todos los datos activos; 2.2 Elija el sistema de archivos correcto: los archivos de datos de MongoDB están preasignados y almacenados en Replicación , los nodos que no sean árbitros de conjuntos maestros y réplicas crearán previamente suficientes archivos vacíos para almacenar registros de operaciones. Estas operaciones de asignación de archivos pueden ser muy lentas en algunos sistemas de archivos, lo que hace que el proceso se bloquee. Por lo tanto, debemos elegir aquellos sistemas de archivos con una asignación de espacio rápida. La conclusión aquí es intentar no usar ext3, usar ext4 o xfs;

3. Optimización de la arquitectura

Deje que los nodos maestro y esclavo se distribuyan en diferentes máquinas tanto como sea posible para evitar operaciones de E/S en la misma máquina que MongoDB;

7. Resumen

MongoDB tiene las características de alto rendimiento, fácil expansión y fácil de usar. Cuando se usa correctamente, su rendimiento sigue siendo muy potente. En algunos puntos clave, como la selección de claves de segmento, el tamaño de la memoria y el disco IO, su el rendimiento es a menudo limitado El mayor cuello de botella. Para la clave fragmentada, en la etapa inicial del sistema comercial, la fragmentación de datos de la colección no se puede realizar primero, porque una vez que se determina la clave fragmentada, no se puede modificar. En la etapa posterior, los campos se pueden filtrar cuidadosamente según a la situación del sistema empresarial.

En general, no se recomienda utilizar claves de fragmentos ascendentes (un campo que crece constantemente con el tiempo, y la clave principal que aumenta automáticamente es una clave ascendente), porque esto conducirá a una lectura y escritura calientes locales, y no puede ejercer el fuerza real del grupo fragmentado. Se recomienda utilizar una clave de fragmento hash o una clave de fragmento distribuida aleatoriamente para garantizar que los datos se distribuyan uniformemente entre los nodos del fragmento. Para la memoria, se recomienda que el tamaño de la memoria incluya el tamaño de los datos activos más el tamaño del índice para garantizar que la memoria pueda contener todos los datos activos. Para los recursos de disco, la lectura y escritura de alta velocidad de MongoDB se basa en la E/S del disco. Para garantizar su rendimiento, se recomienda separar los nodos maestro y esclavo y las aplicaciones de alta E/S para garantizar que los recursos de E/S no se apropien tanto como sea posible.

Enlace original: https://www.jianshu.com/p/f05f65d3a1dc

Supongo que te gusta

Origin blog.csdn.net/LinkSLA/article/details/130236289
Recomendado
Clasificación