El balanceador de MongoDB es un proceso en segundo plano que supervisa la cantidad de datos en cada partición para cada colección particionada. Cuando la cantidad de datos para una colección particionada en una partición dada alcanza niveles específicos umbrales de migración, el balanceador intenta migrar automáticamente los datos entre particiones y alcanzar una cantidad uniforme de datos por partición respetando las zonas. Por defecto, el proceso del balanceador siempre está activado.
El procedimiento de balanceo para clústeres fragmentados es completamente transparente para el usuario y la capa de aplicación, aunque puede haber algún impacto en el rendimiento durante la ejecución del procedimiento.
El balanceador se ejecuta en el primario del set de réplicas del servidor de configuración (CSRS).
Para configurar el balanceo de la colección para una sola colección, consulta
configureCollectionBalancing.
Para administrar el balanceador de clústeres, consulta Gestión del balanceador de clústeres.
Internos del Balanceador
Las migraciones de rango conllevan cierta sobrecarga en términos de ancho de banda y carga de trabajo, lo cual puede afectar el rendimiento de la base de datos. El balanceador intenta minimizar el impacto de la siguiente manera:
Restringir una partición a, como máximo, una migración en un momento dado. Específicamente, una partición no puede participar en múltiples migraciones de datos al mismo tiempo. El balanceador migra los rangos uno a la vez.
MongoDB puede realizar migraciones de datos en paralelo, pero una partición puede participar como máximo en una migración a la vez. Para un clúster particionado con n particiones, MongoDB puede realizar como máximo n/2 migraciones simultáneas (redondeado hacia abajo).
Consulte también Limpieza de migración de rango asincrónica.
Iniciar una ronda de equilibrado solamente cuando la diferencia en la cantidad de datos entre la partición con más datos para una colección particionada y la partición con menos datos para esa colección alcance el umbral de migración.
Se puede desactivar el balanceador temporalmente para tareas de mantenimiento, pero dejar el balanceador desactivado durante periodos prolongados puede degradar el rendimiento del clúster. Para aprender más, consulte Deshabilitar el balanceador.
También se puede limitar el período durante el cual se ejecuta el balanceador para evitar que afecte el tráfico de producción. Consultar Programar el período del balanceo para obtener más detalles.
Nota
La especificación de la ventana de balanceo se refiere a la zona horaria local del primario del set de réplicas del servidor de configuración.
Agregar y remover particiones del clúster
Agregar una partición a un clúster crea un desequilibrio, ya que la nueva partición no tiene datos. Mientras MongoDB comienza a migrar los datos a la nueva partición de inmediato, puede llevar algún tiempo equilibrar el clúster. Consulte el tutorial Agregar particiones a un clúster para obtener instrucciones sobre cómo agregar una partición a un clúster.
Tip
A partir de MongoDB 8.0, puedes redistribuir usando la misma clave para mover datos. Si su aplicación cumple con los requisitos de redistribución de particiones, puede utilizar el comando reshardCollection para redistribuir los datos en todo el clúster y agregar los nuevos fragmentos. Para más información, consulta Reshard a la misma clave de partición. Este proceso es mucho más rápido que la alternativa Procedimiento de migración por rango.
Remover una partición de un clúster crea un desequilibrio similar, ya que los datos que residen en esa partición deben redistribuirse por todo el clúster. Aunque MongoDB empieza a drenar inmediatamente una partición removida, puede pasar algún tiempo antes de que el clúster se equilibre. No apagar los servidores asociados a la partición removida durante este proceso.
Cuando se elimina una partición en un clúster con una distribución desigual de fragmentos, el balanceador primero elimina los fragmentos de la partición en proceso de drenaje y luego equilibra la distribución desigual de fragmentos restante.
Consultar el tutorial Remover particiones de un clúster para obtener instrucciones sobre cómo remover de forma segura una partición de un clúster.
Procedimiento de migración de rango
Todas las migraciones de rangos utilizan el siguiente procedimiento:
El proceso de balanceador envía el comando
moveRangea la partición de origen.La fuente inicia el movimiento cuando recibe un comando interno
moveRange. Durante el proceso de migración, las operaciones al rango se envían a la partición de origen. La partición de origen es responsable de las operaciones de guardado entrantes para el rango.La partición de destino compila cualquier índice requerido por el origen que no exista en el destino.
La partición de destino comienza solicitando documentos en el rango y empieza a recibir copias de los datos. Consulta también Migración y replicación de rango.
Después de recibir el documento final en el rango, la partición de destino inicia un proceso de sincronización para asegurarse de que tiene los cambios en los documentos migrados que ocurrieron durante la migración.
Cuando está completamente sincronizada, la partición de origen se conecta a la base de datos de configuración y actualiza los metadatos del clúster con la nueva ubicación del rango.
Después de que la partición fuente complete la actualización de los metadatos, y una vez que no haya cursores abiertos en el rango, la partición fuente borra su copia de los documentos.
Nota
Si el balanceador necesita realizar migraciones adicionales de fragmentos desde el shard de origen, el balanceador puede iniciar la siguiente migración de fragmentos sin esperar a que el proceso de migración actual termine este paso de eliminación. Ver Limpieza de migración de rango asíncrona.
Advertencia
A partir de la versión 8.2 de MongoDB, las lecturas secundarias de larga duración en un clúster fragmentado pueden terminar automáticamente antes de la eliminación de documentos huérfanos tras una migración de fragmentos.
El parámetro terminateSecondaryReadsOnOrphanCleanup controla este comportamiento. Para obtener más información sobre cómo manejar las lecturas secundarias de larga duración, consulte las lecturas secundarias de larga duración en clústeres particionados.
Umbrales de migración
Para minimizar el impacto del balance en el clúster, el balanceador solo comienza a equilibrar después de que la distribución de datos de una colección particionada haya alcanzado ciertos umbrales.
Una colección se considera equilibrada si la diferencia de datos entre particiones (para esa colección) es inferior a tres veces el tamaño de rango configurado para la colección. Para el tamaño de rango predeterminado de 128MB, dos particiones deben tener una diferencia de tamaño de datos para una determinada colección de al menos 384MB para que se produzca una migración.
Limpieza Asíncrona de Migración de Rango
Para migrar datos desde una partición, el balanceador migra los datos de un rango a la vez. Sin embargo, el balanceador no espera a que se complete la fase de eliminación de la migración actual antes de comenzar la siguiente migración de rango. Consultar Migración de rango para aprender sobre el proceso de migración de rango y la fase de eliminación.
Este comportamiento de cola permite que las particiones descarguen datos más rápidamente en casos de clústeres muy desequilibradas, como al realizar cargas iniciales de datos sin pre-división y al añadir nuevas particiones.
Este comportamiento también afecta el comando moveRange, y los scripts de migración que utilizan el comando moveRange pueden avanzar más rápidamente.
En algunos casos, las fases de eliminación pueden persistir durante más tiempo. Las migraciones de rango se mejoran para ser más resilientes en caso de un cambio por fallas durante la fase de eliminación. Los documentos huérfanos se limpian incluso si el nodo primario de un set de réplicas falla o se reinicia durante esta fase.
Importante
Cuando el campo _waitForDelete está configurado en true, MongoDB no espera el retraso en orphanCleanupDelaySecs antes de realizar la supresión por rango. Si usas el parámetro _waitForDelete y se están realizando operaciones de lectura en secundarios, la lectura podría terminar debido a la fase de eliminación de la migración. Para obtener más información, consulte terminateSecondaryReadsOnOrphanCleanup.
Para más información, consulte Esperar para borrar.
Nota
La eliminación de rangos es una operación intensiva que consume muchos recursos y puede causar un estrés significativo en la caché y en las operaciones de entrada/salida mientras el clúster elimina los documentos.
En los casos en los que se planea mover una gran cantidad de datos, como al agregar particiones a un clúster o durante la distribución inicial de una colección particionada en varias particiones, considera volver a fragmentar la colección. Las operaciones de redistribución no requieren limpieza de rangos, lo que las hace mucho menos exigentes para el clúster.
Para obtener más información, consulta Redistribuir una colección.
Migración y replicación de rangos
Durante la migración de rango, el valor _secondaryThrottle determina cuándo la migración avanza al siguiente documento del rango.
En la colección config.settings:
Si la configuración
_secondaryThrottledel balanceador está configurada en un nivel de confirmación de escritura (write concern), cada documento movido durante la migración de rango debe recibir el acuse de recibo solicitado antes de proceder con el siguiente documento.Si el ajuste
_secondaryThrottleno está configurado, el proceso de migración no espera a que se replique en un secundario y, en su lugar, continúa con el siguiente documento.
Para actualizar el parámetro _secondaryThrottle del balanceador, consulta Acelerador secundario como ejemplo.
Independientemente de cualquier configuración _secondaryThrottle, ciertas fases de la migración por rangos tienen la siguiente política de replicación:
MongoDB pausa brevemente todas las lecturas y escrituras de la aplicación en la colección a la que se está migrando en la partición de origen antes de actualizar los servidores de configuración con la ubicación del rango. MongoDB reanuda las lecturas y escrituras de aplicaciones después de la actualización. El movimiento de rango requiere que todas las escrituras sean reconocidas por la mayoría de los nodos del set de réplicas tanto antes como después de confirmar el movimiento de rango en los servidores de configuración.
Cuando una migración saliente termina y se produce la limpieza, todas las escrituras deben ser replicadas a la mayoría de los servidores antes de que la limpieza adicional (de otras migraciones salientes) o nuevas migraciones entrantes puedan continuar.
Para actualizar la configuración de _secondaryThrottle en la colección config.settings, ver secundario Throttle para un ejemplo.
Cantidad máxima de documentos por rango para migrar
Por defecto, MongoDB no puede mover un rango si el número de documentos en el rango es mayor que 2 veces el resultado de dividir el tamaño del rango configurado por el tamaño promedio de los documentos. Si MongoDB puede mover un subrango de un fragmento y reducir su tamaño a menos de eso, el balanceador lo hace migrando un rango. db.collection.stats() incluye el campo avgObjSize, que representa el tamaño medio de los documentos en la colección.
Para los fragmentos que son demasiado grandes para migrar:
La configuración del balanceador
attemptToBalanceJumboChunkspermite que el balanceador migre fragmentos demasiado grandes para mover, siempre que los fragmentos no estén etiquetados como jumbo. Consulte los rangos de balance que exceden el límite de tamaño para obtener más detalles.Al emitir los comandos
moveRangeymoveChunk, es posible especificar la opción forceJumbo para permitir la migración de rangos que son demasiado grandes para moverse. Los rangos pueden o no estar etiquetados como jumbo.
Optimización del rendimiento de la eliminación por rango
Se puede ajustar el impacto en el rendimiento de las eliminaciones por rango con rangeDeleterBatchSize y rangeDeleterBatchDelayMS.
Por ejemplo:
Para limitar la cantidad de documentos eliminados por lote, puede establecer
rangeDeleterBatchSizeen un valor pequeño, como32.Para añadir un retraso adicional entre las eliminaciones por lotes, se puede establecer
rangeDeleterBatchDelayMSpor encima del valor por defecto actual de20milisegundos.
Nota
Si existen operaciones de lectura en curso o cursores abiertos en la colección objetivo de las eliminaciones, los procesos de eliminación por rangos pueden no continuar.
Change Streams y documentos huérfanos
A partir de MongoDB 5.3, durante la migración de rango, no se generan eventos de flujo de cambios para las actualizaciones de documentos huérfanos.
Tamaño de la partición
Por defecto, MongoDB intenta llenar todo el espacio disponible en disco con datos en cada partición a medida que el conjunto de datos crece. Para garantizar que el clúster siempre tenga la capacidad de gestionar el crecimiento de datos, supervise el uso del disco, así como otras métricas de rendimiento.
Tamaño del fragmento y equilibrio
Para obtener una introducción a chunkSize, consulta Modificar el tamaño del rango en un clúster fragmentado.
Cuando los datos de la colección compartidos entre dos particiones difieren en tres o más veces la configuración de chunkSize, el equilibrador migra los fragmentos entre las particiones.
Por ejemplo, si chunkSize tiene 128 MB y los datos de colección difieren en 384 MB o más, el balanceador migra los fragmentos entre las particiones.
Cuando los fragmentos se mueven, se dividen o se fusionan, los metadatos de la partición se actualizan después de que la operación de fragmento es confirmada por un servidor de configuración. Las Particiones no involucradas en la operación de fragmentos también se actualizan con nuevos metadatos.
El tiempo para la actualización de metadatos de la partición es proporcional al tamaño de la tabla de enrutamiento. Las operaciones CRUD sobre la colección se bloquean temporalmente mientras se actualiza la metadatos de las particiones, y una tabla de enrutamiento más pequeña significa demoras más cortas en las operaciones CRUD.
Desfragmentar una colección reduce el número de fragmentos y el tiempo para actualizar los metadatos del fragmento.
Para reducir la carga de trabajo del sistema, configura el balanceador para que funcione solo en un tiempo específico utilizando una ventana de equilibrio de particiones. La desfragmentación se ejecuta durante el período de tiempo de la ventana de balanceo.
Puede utilizar el parámetro chunkDefragmentationThrottlingMS para limitar la velocidad de los comandos de división y fusión ejecutados por el balanceador.
Puedes iniciar y detener la desfragmentación en cualquier momento.
También puedes establecer una zona de particiones. Una zona de particiones se basa en la clave de partición, y se puede asociar cada zona con una o más particiones en un clúster.
Un clúster particionado solo divide fragmentos cuando es necesario migrarlos. Esto significa que el tamaño del fragmento puede superar chunkSize. Los fragmentos más grandes reducen el número de fragmentos en una partición y mejoran el rendimiento al reducir el tiempo necesario para actualizar los metadatos de la partición. Por ejemplo, es posible que se vea un fragmento de 1 TB en una partición aunque hayas configurado chunkSize en 256 MB.
chunkSize afecta a lo siguiente:
Cantidad máxima de datos que el balanceador intenta migrar entre dos particiones en una única operación de migración de fragmentos.
Cantidad de datos migrados durante la desfragmentación.
Para detalles sobre la desfragmentación de colecciones fragmentadas, consulte Desfragmentar colecciones fragmentadas.
Se pueden redistribuir los fragmentos para equilibrar
Cuando se ejecuta el método sh.shardCollection(), el balanceador comienza a distribuir los datos de la colección a otras particiones del clúster. Una sola partición solo puede participar en una migración de fragmento a la vez. Cuando MongoDB copia un rango de datos de una partición a otra correctamente, el rango en la partición donante se marca para su eliminación por el eliminador de rangos. Este proceso es lento y requiere muchos recursos.
A partir de MongoDB 8.0, si la implementación cumple los requisitos de recursos, se recomienda usar el método sh.shardAndDistributeCollection() para particionar la colección. Este método encapsula los comandos shardCollection y reshardCollection para particionar la colección y redistribuirla de inmediato con la misma clave. Esto hace que MongoDB vuelva a equilibrar los datos entre las particiones sin esperar al balanceador.
Para obtener más información, se puede consultar Redistribuir con la misma clave de partición.