Adicionar um novo shard é a forma padrão de escalar horizontalmente um cluster MongoDB com sharding. No entanto, os dados nem sempre se redistribuem automaticamente — o novo shard pode ficar ocioso enquanto os antigos permanecem sobrecarregados. Este tópico apresenta um processo sistemático para diagnosticar a falta de balanceamento e resolver o desequilíbrio.
Como funciona o balanceamento
O equilíbrio de dados entre shards depende inteiramente do balancer nativo do MongoDB. Esse componente redistribui os dados migrando chunks de shards sobrecarregados para aqueles com menor carga. Se o balancer não estiver em execução, estiver mal configurado ou propriedades da coleção o bloquearem, os chunks permanecerão em seus locais originais.
O diagnóstico envolve duas etapas:
Estado do balancer — Confirme se o balancer está ativado, ativo e executando dentro de uma janela válida.
Migração de dados — Identifique propriedades da coleção que impedem o balancer de mover dados, como coleções sem sharding, volumes abaixo do limiar de balanceamento ou presença de jumbo chunks.
Diagnosticar o estado do balancer
O balancer é o único mecanismo responsável pela migração de chunks. Comece por aqui antes de investigar outros aspectos.
Verificar se o balancer está ativado
No mongosh, execute:
sh.getBalancerState()
Se a saída for false, o balancer está desativado. Ative-o seguindo as instruções em Gerencie o balancer do MongoDB.
Verificar a janela ativa
O balancer executa apenas durante sua janela ativa configurada. Fora desse período, nenhuma migração ocorre.
Para verificar a configuração da janela ativa, execute o comando:
db.getSiblingDB("config").settings.find({_id:"balancer"})
Exemplo de saída:
{ _id: 'balancer', activeWindow: { start: '02:00', stop: '04:00' } }
Caso a janela seja muito curta ou coincida com horários de pico de tráfego, estenda-a para cobrir um período maior fora do pico. O exemplo a seguir define a janela diária das 02:00 às 06:00:
db.getSiblingDB("config").settings.updateOne(
{ _id: "balancer" },
{ $set: { activeWindow: { start: "02:00", stop: "06:00" } } },
{ upsert: true }
)
Verificar se o balanceamento já está em andamento
Após adicionar um shard, o balancer precisa de tempo para migrar os dados existentes. É esperado haver desequilíbrio durante esse período.
Para verificar se há uma tarefa de migração ativa, execute:
sh.isBalancerRunning()
Se a saída for true, o balanceamento está em andamento. Aguarde a conclusão. Para acompanhar o progresso, consulte Como verificar o progresso da adição ou remoção de um nó shard.
Analisar a possibilidade de migração de dados
Se o balancer estiver ativado e em execução, mas os dados não se moverem, o problema provavelmente reside nas propriedades da coleção. As condições a seguir podem bloquear a migração.
Verificar grandes coleções sem sharding
Um banco de dados pode conter coleções com e sem sharding. Coleções sem sharding armazenam todos os dados no shard primário do banco — o balancer não consegue migrá-los. Se suas maiores coleções não tiverem sharding, elas nunca alcançarão o novo shard.
Execute o script a seguir para calcular o armazenamento ocupado por coleções sem sharding em um determinado banco de dados:
// Replace "myDB" with the name of the database to check
var dbName = "myDB";
var unshardSize = 0;
var totalSize = 0;
var unshardedCollections = [];
db.getSiblingDB(dbName).getCollectionNames().forEach(function(collName) {
var stats = db.getSiblingDB(dbName).getCollection(collName).stats();
// Check the stats.sharded field and add up the storage size
if (!stats.sharded) {
unshardSize += (stats.storageSize || 0);
unshardedCollections.push(dbName + "." + collName);
}
totalSize += (stats.storageSize || 0);
// Sleep briefly after each query to avoid excessive load on the database
sleep(200);
});
print("--- " + dbName + " ---");
print("Unsharded Collections Count: " + unshardedCollections.length);
print("--------------------");
print("Unsharded Storage Size (Bytes): " + unshardSize);
print("Total Storage Size (Bytes): " + totalSize);
print("--------------------");
print("Unsharded Collections List:");
printjson(unshardedCollections);
Este script chamastats()em cada coleção, o que pode afetar o desempenho do banco de dados. O atraso integradosleep(200)reduz esse risco. Para bancos de dados com muitas coleções, aumente o atraso para2000ou mais.
Se as coleções sem sharding representarem uma parcela significativa do armazenamento, ative o sharding nelas. Para obter orientações, consulte Configurar sharding de dados para aproveitar totalmente o desempenho dos shards.
Verificar se coleções com sharding estão abaixo do limiar de migração (MongoDB 6.0+)
A partir do MongoDB 6.0.3, o balancer só migra chunks quando a diferença de volume de dados entre shards para uma determinada coleção atinge um limiar. O valor padrão corresponde a três vezes o tamanho do chunk.
Com o tamanho padrão de chunk de 128 MB, o desequilíbrio de dados entre dois shards deve atingir pelo menos 384 MB antes que o balancer acione a migração para essa coleção. Coleções com volume total inferior a esse limiar são consideradas equilibradas e não sofrem alterações.
Para verificar a distribuição dos dados de uma coleção entre os shards, execute:
db.<collection>.getShardDistribution()
Se a maior parte dos dados de uma coleção com sharding estiver concentrada em um único shard e o desequilíbrio for inferior a 384 MB (considerando o tamanho padrão de chunk), o balancer não agirá. Reduza o chunkSize da coleção para diminuir o limiar e acionar a migração:
// This example sets chunkSize to 16 MB for test_db.test_coll.
// Adjust chunkSize based on your collection's data volume and distribution.
db.adminCommand({
configureCollectionBalancing: "test_db.test_coll",
chunkSize: 16 // Unit: MB. Default for MongoDB 6.0+: 128 MB
})
Após a conclusão da migração, verifique se a distribuição melhorou:
db.<collection>.getShardDistribution()
Considerações sobre desempenho e configuração
Sobrecarga de desempenho do balanceamento
A migração de chunks (moveChunk) e a subsequente exclusão de intervalos (RangeDeleter) consomem CPU e E/S de disco tanto nos shards de source quanto nos de destino. Para evitar impactos no tráfego online, defina a janela ativa do balancer para horários fora do pico.
Risco de configuração de chunkSize (versões do MongoDB anteriores à 6.0)
Em versões do MongoDB anteriores à 6.0, definir o chunkSize com um valor muito pequeno pode criar um número excessivo de chunks. Isso aumenta a sobrecarga de metadados no config server e faz com que o balancer execute com muita frequência. Defina o chunkSize com base no volume total de dados e na taxa de crescimento esperada da coleção.