Este tópico descreve como monitorar o progresso de tarefas de adição ou remoção de nós shard e identificar condições anormais que podem bloquear essas operações.
Informações básicas
Após adicionar ou remover nós shard de uma instância de cluster com sharding, a tarefa pode permanecer incompleta por um longo período. As seções a seguir explicam como solucionar esse problema.
Antes de começar, compreenda os seguintes conceitos:
Modos de implantação de instâncias de conjunto de réplicas e de clusters com sharding do MongoDB, bem como as diferenças entre essas arquiteturas. Para mais informações, consulte Replica set architecture e Sharded cluster architecture.
Funcionamento do Balancer do MongoDB. Para mais detalhes, consulte Manage the MongoDB Balancer.
Divisão de dados pelo MongoDB. O MongoDB particiona os dados em chunks.
Comandos comuns de O&M para instâncias de cluster com sharding do MongoDB, como
sh.status().Uso do mongo shell, mongosh ou outras ferramentas de visualização.
Verificar o progresso da tarefa
Etapa 1: Verificar se o Balancer está ativado
A migração de chunks durante a adição ou remoção de shards depende do Balancer. Se o Balancer estiver desativado, ocorrerão os seguintes problemas:
Ao adicionar um nó shard: os dados dos chunks não migram para o novo nó shard, impedindo que o nó processe tráfego de serviço.
Ao remover um nó shard: os chunks no shard de destino não migram, bloqueando a tarefa de remoção.
Ative o Balancer para garantir a migração normal de chunks. Para obter instruções, consulte Manage the MongoDB Balancer.
Utilize um dos métodos abaixo para verificar se o Balancer está ativado:
-
Método 1: Execute o comando
sh.status().Se o Balancer estiver ativado, a saída será semelhante ao exemplo a seguir.
... autosplit: Currently enabled: yes balancer: Currently enabled: yes Currently running: yes Balancer active window is set between 08:30 and 11:30 server local time ...Caso a saída exiba
“Currently enabled: no”, o Balancer está desativado. -
Método 2: Execute o comando
sh.getBalancerState().Se o comando retornar
true, o Balancer está ativado.Se o retorno for
false, o Balancer está desativado.
Etapa 2: Verificar se a janela do Balancer é muito curta
O Balancer controla a velocidade de migração de chunks e realiza migrações apenas durante sua janela ativa. Se a migração não for concluída dentro da janela atual, ela continuará na próxima janela até terminar. Uma janela curta pode retardar as tarefas de adição ou remoção de shards. Para ajustar a janela do Balancer, consulte Manage the MongoDB Balancer.
Use um dos métodos a seguir para verificar a janela do Balancer:
-
Método 1: Execute o comando
sh.status().O exemplo abaixo mostra uma janela do Balancer das 08:30 às 11:30 no horário local do servidor (total de 3 horas).
... autosplit: Currently enabled: yes balancer: Currently enabled: yes Currently running: yes Balancer active window is set between 08:30 and 11:30 server local time ... -
Método 2: Execute o comando
sh.getBalancerWindow().O exemplo seguinte exibe claramente o horário da janela, sendo especialmente útil quando existem muitas coleções com sharding.
{ "start" : "08:30", "stop" : "11:30" }
Etapa 3: Coletar informações necessárias para estimar o progresso da tarefa
Para versões do MongoDB anteriores à 6,0
Esta seção aplica-se às seguintes versões:
Instâncias do MongoDB anteriores à versão 6,0.
Instâncias do MongoDB 6.0 com versão secundária do mecanismo anterior a 7.0.1 (versão base 6.0.3). Para verificar sua versão secundária do mecanismo, consulte MongoDB minor version guide.
Antes de estimar o progresso da tarefa, obtenha estatísticas de execução do Balancer (contagens de sucesso e falha) e informações sobre chunks de coleções com sharding pendentes de migração.
Obtenha os resultados de execução do Balancer e informações sobre chunks de tabelas com sharding pendentes de migração usando os dois métodos a seguir:
-
Método 1: Utilize a saída do comando
sh.status().Concentre-se em duas partes da saída do
sh.status(). A primeira parte mostra os resultados recentes do Balancer, conforme este exemplo.... balancer: Collections with active migrations: <db>.<collection> started at Wed Sep 27 2023 10:25:21 GMT+0800 (CST) Failed balancer rounds in last 5 attempts: 0 Migration Results for the last 24 hours: 300 : Success databases: ...A segunda parte exibe detalhes dos chunks para coleções com sharding, como neste exemplo.
... databases: ... { "_id" : "<db>", "primary" : "d-xxxxxxxxxxxxxxx3", "partitioned" : true, "version" : { "uuid" : UUID("3409a337-c370-4425-ad72-8b8c6b0abd52"), "lastMod" : 1 } } <db>.<collection> shard key: { "<shard_key>" : "hashed" } unique: false balancing: true chunks: d-xxxxxxxxxxxxxxx1 13630 d-xxxxxxxxxxxxxxx2 13629 d-xxxxxxxxxxxxxxx3 13652 d-xxxxxxxxxxxxxxx4 13630 d-xxxxxxxxxxxxxxx5 3719 too many chunks to print, use verbose if you want to force print ...Neste exemplo, “d-xxxxxxxxxxxxxxx5” é o nó shard recém-adicionado. Também é possível executar o comando
getShardDistributionno banco de dados que contém a coleção com sharding para obter detalhes da distribuição de chunks, conforme mostrado abaixo.use <db> db.<collection>.getShardDistribution() -
Método 2: Leia os dados relevantes diretamente do banco de dados config.
Visualize estatísticas de chunks agregadas por shard da seguinte forma.
db.getSiblingDB("config").chunks.aggregate([{$group: {_id: "$shard", count: {$sum: 1}}}])Para visualizar chunks em um shard específico agrupados por namespace, execute o comando a seguir.
db.getSiblingDB("config").chunks.aggregate([{$match: {shard: "d-xxxxxxxxxxxxxx"}},{$group: {_id: "$ns", count: {$sum: 1}}}])Para contar chunks migrados com sucesso para um nó shard específico nas últimas 24 horas, execute o comando abaixo.
// details.to specifies the destination shard for chunk migration // Use ISODate to define the time range in the time field db.getSiblingDB("config").changelog.find({"what" : "moveChunk.commit", "details.to" : "d-xxxxxxxxxxxxx","time" : {"$gte": ISODate("2023-09-26T00:00:00")}}).count()
Para versões do MongoDB 6.0 e posteriores
Esta seção aplica-se às seguintes versões:
Instâncias do MongoDB versão 6.0 e posteriores.
Instâncias do MongoDB 6.0 com versão secundária do mecanismo 7.0.1 (versão base 6.0.3) ou posterior. Para verificar sua versão secundária do mecanismo, consulte MongoDB minor version guide.
Antes de estimar o progresso da tarefa, concentre-se na distribuição de dados entre os shards. Ainda é possível usar a saída do sh.status() como referência, mas mude o foco da contagem desigual de chunks para a distribuição real do volume de dados.
-
Obtenha informações sobre a distribuição de coleções com sharding e o equilíbrio de dados.
Use o comando
getShardDistributionpara obter detalhes da distribuição e focar no equilíbrio dos dados. Exemplo:mongos> db.xxx.getShardDistribution() Shard d-xxx at xxx data : 379.26MiB docs : 8277367 chunks : 1 estimated data per chunk : 379.26MiB estimated docs per chunk : 8277367 Shard d-xxx at xxx data : 379.11MiB docs : 8272852 chunks : 1 estimated data per chunk : 379.11MiB estimated docs per chunk : 8272852 Shard d-xxx at xxx data : 379.18MiB docs : 8275108 chunks : 1 estimated data per chunk : 379.18MiB estimated docs per chunk : 8275108 Totals data : 1.11GiB docs : 24825327 chunks : 3 Shard d-xxx contains 33.34% data, 33.34% docs in cluster, avg obj size on shard : 48B Shard d-xxx contains 33.32% data, 33.32% docs in cluster, avg obj size on shard : 48B Shard d-xxx contains 33.33% data, 33.33% docs in cluster, avg obj size on shard : 48BTambém é possível executar o comando a seguir para obter informações de distribuição mais detalhadas (incluindo contagem de documentos, tamanho total, contagem de documentos órfãos e tamanho dos órfãos):
db.getSiblingDB("admin").aggregate( [{ $shardedDataDistribution: { } },{ $match: { "ns": "<db>.<collection>" } }] ).pretty()A saída de exemplo a seguir mostra um desequilíbrio notável de dados entre os shards.
{ "ns" : "<db>.<collection>", "shards" : [ { "shardName" : "d-xxxxxxxxxxxxxxx1", "numOrphanedDocs" : 0, "numOwnedDocuments" : 504298920, "ownedSizeBytes" : NumberLong("833101815840"), "orphanedSizeBytes" : 0 }, { "shardName" : "d-xxxxxxxxxxxxxxx2", "numOrphanedDocs" : 0, "numOwnedDocuments" : 250283901, "ownedSizeBytes" : NumberLong("409714745937"), "orphanedSizeBytes" : 0 }, { "shardName" : "d-xxxxxxxxxxxxxxx3", "numOrphanedDocs" : 0, "numOwnedDocuments" : 109098088, "ownedSizeBytes" : NumberLong("178157177704"), "orphanedSizeBytes" : 0 }, { "shardName" : "d-xxxxxxxxxxxxxxx4", "numOrphanedDocs" : 0, "numOwnedDocuments" : 382018055, "ownedSizeBytes" : NumberLong("630329790750"), "orphanedSizeBytes" : 0 } ] }Com base nessa saída, é possível determinar que a instância possui 4 nós shard e o volume total de dados da coleção com sharding
<db>.<collection>é de aproximadamente 2051303530231 bytes (833101815840 + 409714745937 + 178157177704 + 630329790750 = 2051303530231), ou cerca de 1910,4 GB. -
Visualize o volume de dados migrado com sucesso no último dia.
Execute a consulta a seguir:
pipeline = [ { '$match': { 'what': 'moveChunk.commit', } }, { '$group': { '_id': { 'date': { '$dateToString': { 'format': '%Y-%m-%d', 'date': '$time'} }, }, 'chunks_moved': { '$sum': 1 }, 'docs_moved': { '$sum': '$details.counts.cloned' }, 'bytes_moved': { '$sum': '$details.counts.clonedBytes' }, } }, { '$sort': { '_id.date': -1} }, ] db.getSiblingDB("config").changelog.aggregate(pipeline)Exemplo de saída:
mongos> db.getSiblingDB("config").changelog.aggregate(pipeline) { "_id" : { "date" : "2024-09-24" }, "chunks_moved" : 91, "docs_moved" : NumberLong(33071040), "bytes_moved" : NumberLong("11532786734") } { "_id" : { "date" : "2024-09-23" }, "chunks_moved" : 294, "docs_moved" : NumberLong(109806635), "bytes_moved" : NumberLong("38294757573") } { "_id" : { "date" : "2024-09-22" }, "chunks_moved" : 737, "docs_moved" : NumberLong(266800041), "bytes_moved" : NumberLong("93047288531") } { "_id" : { "date" : "2024-09-21" }, "chunks_moved" : 1448, "docs_moved" : NumberLong(525308393), "bytes_moved" : NumberLong("183117965820") } { "_id" : { "date" : "2024-09-20" }, "chunks_moved" : 1459, "docs_moved" : NumberLong(530020503), "bytes_moved" : NumberLong("184390749022") } { "_id" : { "date" : "2024-09-19" }, "chunks_moved" : 1478, "docs_moved" : NumberLong(557833705), "bytes_moved" : NumberLong("186910196651") } { "_id" : { "date" : "2024-09-18" }, "chunks_moved" : 1360, "docs_moved" : NumberLong(508484825), "bytes_moved" : NumberLong("173486932689") }Essa saída indica que em
2024-09-21, foram migrados 183117965820 bytes (cerca de 170,5 GB).
Etapa 4: Estimar o progresso da tarefa e o tempo de conclusão
Para versões do MongoDB anteriores à 6,0
Esta seção aplica-se às seguintes versões:
Instâncias do MongoDB anteriores à versão 6,0.
Instâncias do MongoDB 6.0 com versão secundária do mecanismo anterior a 7.0.1 (versão base 6.0.3). Para verificar sua versão secundária do mecanismo, consulte MongoDB minor version guide.
Após obter o número de chunks migrados com sucesso e a distribuição atual de dados, estime o progresso geral da tarefa e o tempo esperado para conclusão.
Considere as seguintes condições ideais durante a adição de shards: a contagem total de chunks permanece constante, a quantidade de shards é fixa (sem adições ou remoções simultâneas), a carga do serviço mantém-se estável e os parâmetros do Balancer usam valores padrão. Usando o exemplo de Step 3 em Para versões do MongoDB anteriores à 6,0, sabe-se que:
Existem 5 nós shard.
300 chunks foram migrados com sucesso durante a janela do Balancer.
A coleção com sharding
<db>.<collection>possui 58260 chunks no total (13630 + 13629 + 13652 + 13630 + 3719 = 58260).
Portanto, é possível calcular o seguinte:
Em equilíbrio, cada shard deve conter 11652 chunks (58260 ÷ 5 = 11652).
Na taxa atual de migração, a conclusão da tarefa requer mais 26,4 dias ((11652 – 3719) ÷ 300 ≈ 26,4).
A tarefa de adição de shard está 32% concluída (3719 ÷ 11652 = 32%).
Em cenários reais, a contagem total de chunks aumenta devido a gravações contínuas e divisões de chunks. Este cálculo assume condições ideais; o tempo real de conclusão pode ser maior.
Para versões do MongoDB 6.0 e posteriores
Esta seção aplica-se às seguintes versões:
Instâncias do MongoDB versão 6.0 e posteriores.
Instâncias do MongoDB 6.0 com versão secundária do mecanismo 7.0.1 (versão base 6.0.3) ou posterior. Para verificar sua versão secundária do mecanismo, consulte MongoDB minor version guide.
Suponha que a instância de cluster com sharding tenha apenas uma coleção que precise de balanceamento. Usando o exemplo de Step 3 em Para versões do MongoDB 6.0 e posteriores, sabe-se que:
Existem 4 nós shard.
Em
2024-09-21, aproximadamente 170,5 GB (183117965820 bytes) foram migrados.A coleção com sharding
<db>.<collection>tem um volume total de dados de cerca de 1910,4 GB (2051303530231 bytes).
Assim, pode-se calcular o seguinte:
Em equilíbrio, cada shard deve conter aproximadamente 477,6 GB (512825882557,75 bytes).
-
O volume total de dados que precisa ser migrado para atingir o equilíbrio é de 875559682949 bytes (815,4 GB), detalhado da seguinte forma:
O Shard1 precisa migrar 320275933282,25 bytes (833101815840 – 512825882557,75).
O Shard2 precisa migrar 103111136620,75 bytes (409714745937 – 512825882557,75).
O Shard3 precisa migrar 334668704853,75 bytes (178157177704 – 512825882557,75).
O Shard4 precisa migrar 117503908192,25 bytes (630329790750 – 512825882557,75).
(320275933282,25 + 103111136620,75 + 334668704853,75 + 117503908192,25 = 875559682949)
Na taxa atual de migração, o equilíbrio será atingido em cerca de 4,8 dias (815,4 GB ÷ 170,5 GB/dia ≈ 4,8 dias).
Etapa 5: Verificar se o fluxo da tarefa está bloqueado (remoção de shard)
Se a tarefa de remoção de shard estiver bloqueada, a saída do sh.status() não mostrará migrações de chunks bem-sucedidas nos períodos recentes, e o shard em remoção ainda terá chunks não migrados. Nesse caso, a tarefa de remoção de shard não consegue ser concluída, e outras operações de O&M na instância no console do ApsaraDB for MongoDB também são afetadas.
O exemplo a seguir mostra a saída do sh.status() nesse cenário.
autosplit:
Currently enabled: yes
balancer:
Currently enabled: yes
Currently running: no
Balancer lock taken at Wed Sep 30 2020 02:03:11 GMT+0800 (CST) by ConfigServer:Balancer
Failed balancer rounds in last 5 attempts: 0
Migration Results for the last 24 hours:
No recent migrations
databases:
{ "_id" : "report", "primary" : "d-0xixxx", "partitioned" : true }
report.report
shard key: { "GsId" : "hashed" }
unique: false
balancing: true
chunks:
d-0xixxx 9
d-0xixxx 2133
d-0xixxx 2152
d-0xixxx 2116
d-0xixxx 2133
too many chunks to print, use verbose if you want to force print
Esse problema provavelmente é causado por jumbo chunks que bloqueiam o processo de remoção do shard. Execute o comando a seguir para verificar a existência de jumbo chunks.
db.getSiblingDB("config").chunks.aggregate([{$match: {shard: "d-xxxxxxxxxxxxxx", jumbo:true}},{$group: {_id: "$ns", count: {$sum: 1}}}])
Jumbo chunks geralmente resultam de um design inadequado de chave de shard, como hot keys. Antes de prosseguir, classifique os jumbo chunks em uma das categorias a seguir:
Divisível: O tamanho do chunk excede
chunkSize, mas o chunk ainda pode ser dividido em chunks menores com base na chave de shard. Nenhum tratamento especial é necessário. O Balancer migrará o chunk após ele ser dividido.Indivisível: A maioria dos dados no chunk compartilha o mesmo valor de chave de shard (hot key). O tamanho dos dados excede
chunkSizee o chunk não pode ser dividido. Use um dos métodos a seguir para lidar com esse tipo.
Experimente os métodos a seguir de acordo com seus requisitos de negócio:
-
Método 1: Otimizar o design da chave de shard (correção definitiva para problemas de hot key)
Para MongoDB 4.4 ou posterior, utilize o comando refineCollectionShardKey para adicionar campos de sufixo à chave de shard existente. Isso aumenta a cardinalidade da chave de shard e torna divisíveis os jumbo chunks anteriormente indivisíveis.
Para MongoDB 5.0 ou posterior, também é possível usar o comando reshardCollection para refazer o sharding da coleção com uma nova chave de shard. Para mais informações, consulte Reshard a Collection.
-
Método 2: Migrar o jumbo chunk (para MongoDB 4.4 ou posterior, como quando um jumbo chunk não pode ser migrado durante a remoção de shard)
-
Opção 1 (recomendada): Execute o comando clearJumboFlag para limpar a flag jumbo do chunk e, em seguida, defina o parâmetro do Balancer
attemptToBalanceJumboChunkscomotruepara permitir que o Balancer migre o chunk automaticamente. Este método não bloqueia gravações durante a cópia de dados. As gravações são bloqueadas apenas brevemente durante a fase final da migração.ImportanteSe o volume de gravação no chunk for alto, a migração poderá falhar devido a estouro do cache incremental. Após a falha, o chunk é marcado novamente como jumbo. Limpe a flag novamente e tente outra vez.
Após a migração bem-sucedida, defina imediatamente
attemptToBalanceJumboChunksde volta parafalse. Para MongoDB 6.0 ou posterior, o Balancer faz o balanceamento com base nas diferenças de volume de dados entre os shards. Depois que o chunk superdimensionado é migrado para qualquer shard, esse shard torna-se o ponto fora da curva em volume de dados. Se você não restaurar a configuração, o Balancer migrará o chunk de um lado para o outro entre os shards, causando transferência contínua de dados e sobrecarga de limpeza de documentos órfãos. Ao restaurar a configuração, o chunk será marcado novamente como jumbo quando a próxima tentativa regular de migração falhar e não será mais movido. Isso é esperado e não exige que a flag seja limpa novamente.
Opção 2: Execute o comando
moveChunkcom a opçãoforceJumbo: true. Este método bloqueia todas as gravações na coleção no shard de origem durante a cópia de dados, o que pode durar horas para chunks grandes. Utilize este método apenas fora do horário de pico ou quando as gravações puderem ser pausadas. Recomendamos realizar esta operação com assistência do suporte técnico da Alibaba Cloud.
-
Método 3: Excluir dados. Se alguns dados de negócio puderem ser excluídos, remova dados do jumbo chunk para reduzir seu tamanho. Nota: Após o chunk ficar menor, a flag jumbo não é limpa automaticamente. Você ainda deve executar o comando
clearJumboFlag(ou aguardar até que o chunk seja dividido com sucesso) antes que o Balancer possa migrá-lo.Método 4: Aumentar o parâmetro chunkSize. Aumente o parâmetro
chunkSizepara alterar o limiar de jumbo chunk. Este método é eficaz apenas quando o tamanho real do chunk excede ligeiramente o limiar atual. Ele não ajuda com chunks superdimensionados causados por hot keys. Recomendamos realizar esta operação com assistência do suporte técnico da Alibaba Cloud.
Se nenhum dos métodos anteriores resolver o problema, envie um ticket para entrar em contato com o suporte técnico.
Acelerar processos de tarefas de adição ou exclusão
Para concluir a adição ou remoção de shards mais rapidamente, experimente estes métodos de aceleração:
Aumente a duração da janela do Balancer. Observe que a migração de chunks adiciona carga extra que pode afetar seu serviço. Avalie os riscos antes de ajustar. Para instruções, consulte Manage the MongoDB Balancer.
Ajuste o parâmetro setParameter.chunkMigrationConcurrency para alterar a concorrência de migração de chunks. Para detalhes, veja Parameter tuning recommendations.
-
Execute manualmente operações
moveChunkfora do horário de pico. Para mais informações, consulte sh.moveChunk(). Exemplo:sh.moveChunk("<db>.<collection>", {"<shard_key>": <value>}, "d-xxxxxxxxxxxxx") // example: sh.moveChunk("records.people", { zipcode: "53187" }, "shard0019") envie um ticket para solicitar ajustes de parâmetros de kernel ao suporte técnico.