Refragmentar uma collection
Nesta página
- Sobre esta tarefa
- Antes de começar
- Passos
- Inicie a operação de refragmentação.
- Monitore a operação de refragmentação.
- Conclua a operação de refragmentação.
- Inicie o bloqueio das gravações com antecedência para forçar a conclusão da refragmentação
- Abortar operação de refragmentação
- Comportamento
- Duração mínima de uma operação de refragmentação
- Gravações repetíveis
- Casos de erro
- Failovers primários
- Duplicate
_id
Values
Novidades na versão 5.0.
A chave de fragmento ideal permite que o MongoDB distribua documentos uniformemente em todo o cluster, ao mesmo tempo em que facilita padrões de consultas comuns. Uma chave de fragmento abaixo do ideal pode levar a problemas de desempenho ou dimensionamento devido à distribuição desigual de dados. A partir do MongoDB 5.0, você pode alterar a chave de fragmento de uma coleção para mudar a distribuição de seus dados em um cluster.
Observação
Antes de refragmentar sua coleção, leia Solucionar problemas de chaves de Shard para obter informações sobre problemas comuns de desempenho e escalabilidade e conselhos sobre como corrigi-los.
Sobre esta tarefa
Somente uma coleção pode ser refragmentada de cada vez.
writeConcernMajorityJournalDefault
deve sertrue
.Para refragmentar uma collection que tenha uma restrição de exclusividade, a nova chave de shard deve satisfazer os requisitos de índice únicos para quaisquer índices únicos existentes.
Os comandos a seguir e os métodos de shell correspondentes não são compatíveis com a collection que está sendo refragmentada enquanto a operação de refragmentação está em andamento:
Os seguintes comandos e métodos não são suportados no cluster enquanto a operação de refragmentação está em andamento:
Aviso
Usar qualquer um dos comandos anteriores durante uma operação de refragmentação faz com que a operação de refragmentação falhe.
Se a collection a ser refragmentada usar Atlas Search, o índice de pesquisa ficará indisponível quando a operação de refragmentação for concluída. Você precisa refragmentar manualmente o índice de pesquisa assim que a operação de refragmentação for concluída.
Antes de começar
Antes de refragmentar sua collection, certifique-se de atender aos seguintes requisitos:
Seu aplicativo pode tolerar um período de dois segundos em que a collection que está sendo refragmentada bloqueia as gravações. Durante o período em que as gravações são bloqueadas, seu aplicativo experimenta um aumento na latência. Se seu volume de trabalho não tolerar esse requisito, considere ajustar sua chave de shard.
Seu banco de dados atende aos seguintes requisitos de recursos:
Espaço de armazenamento disponível: certifique-se de que o espaço de armazenamento disponível em cada shard em que a collection será distribuída seja pelo menos duas vezes o tamanho da collection que você deseja refragmentar e seu tamanho de índice total, dividido pelo número de shards.
storage_req = ( ( collection_size + index_size ) * 2 ) / shard_count Por exemplo, considere uma collection que contém 2 TB de dados e tem um índice 400 GB distribuído em quatro shards. Para realizar uma operação de refragmentação nessa collection, cada shard exigiria 1.2 TB de armazenamento disponível.
1.2 TB storage = ( ( 2 TB collection + 0.4 TB index ) * 2 ) / 4 shards Para atender aos requisitos de armazenamento, talvez seja necessário atualizar para o próximo nível de armazenamento durante a operação de refragmentação. Você pode reduzir assim que a operação for concluída.
E/S: certifique-se de que sua capacidade de E/S esteja abaixo de 50%.
Carga da CPU: certifique-se de que a carga da CPU esteja abaixo de 80%.
Importante
Esses requisitos não são exigidos pelo banco de dados. Uma falha na alocação de recursos suficientes pode resultar em:
o banco de dados ficar sem espaço e desligando
redução do desempenho
a operação de refragmentação demora mais que o esperado
Se o seu aplicativo tiver períodos com menos tráfego, refaça a fragmentação da sua collection durante esse período, se possível.
Você deve reescrever as queries do seu aplicativo para usar ambas as chaves de shard, a atual e a nova.
Dica
Se o seu aplicação tolerar o tempo de inatividade, você poderá executar estas etapas para evitar reescrever as queries do aplicativo para usar as chaves de shard atuais e as novas:
Pare seu aplicativo.
Reescreva seu aplicação para usar a nova chave de shard.
Aguarde até que a refragmentação seja concluída. Para monitorar o processo de refragmentação, use o estágio de pipeline
$currentOp
.Implemente seu aplicação reescrito.
Antes da conclusão da refragmentação, as seguintes queries retornam um erro se o filtro de query não incluir a chave de shard atual ou um campo exclusivo (como
_id
):Para um desempenho ideal, recomendamos que você também reescreva outras queries para incluir a nova chave de shard.
Quando a operação de refragmentação for concluída, você poderá remover a chave de shard antiga das consultas.
Nenhuma construção de índice está em andamento. Use
db.currentOp()
para verificar qualquer construção de índice está em execução:db.adminCommand( { currentOp: true, $or: [ { op: "command", "command.createIndexes": { $exists: true } }, { op: "none", "msg" : /^Index Build/ } ] } ) No documento de resultado, se o valor do campo
inprog
for uma array vazia, não haverá nenhuma construção de índice em andamento:{ inprog: [], ok: 1, '$clusterTime': { ... }, operationTime: <timestamp> }
Observação
A refragmentação é um processo de gravação intensiva que pode gerar taxas maiores de oplog. Talvez você queira:
definir um tamanho fixo de oplog para prevenir o crescimento ilimitado do oplog.
aumentar o tamanho do oplog para minimizar a chance de um ou mais nós secundários se tornarem obsoletos.
Consulte a documentação Conjunto de réplicas do Oplog para obter mais detalhes.
Passos
Importante
É altamente recomendável que você verifique a seção Sobre esta tarefa e leia a seção Etapas na íntegra antes de refragmentar sua collection.
Em uma operação de refragmentação de collection, um fragmento (shard) pode ser um:
doador, que atualmente armazena chunks para a coleção fragmentada.
receptor, que armazena novos chunks para a coleção fragmentada com base nas chaves de fragmento e nas zonas.
Um shard pode ser doador e um receptor ao mesmo tempo. O conjunto de shards do doador é idêntico aos shards do receptor, a menos que você use zonas.
O servidor de configuração primário é sempre o gerenciador de refragmentação e inicia cada fase da operação de refragmentação.
Inicie a operação de refragmentação.
Enquanto conectado ao mongos
, emita um comando reshardCollection
que especifica a collection a ser refragmentada e a nova chave de shard:
db.adminCommand({ reshardCollection: "<database>.<collection>", key: <shardkey> })
O MongoDB define o número máximo de segundos para bloquear gravações para dois segundos e inicia a operação de refragmentação.
Monitore a operação de refragmentação.
Para monitorar a operação de refragmentação, você pode usar o estágio de pipeline$currentOp
:
db.getSiblingDB("admin").aggregate([ { $currentOp: { allUsers: true, localOps: false } }, { $match: { type: "op", "originatingCommand.reshardCollection": "<database>.<collection>" } } ])
Observação
Para ver os valores atualizados, você precisa executar continuamente o pipeline anterior.
As saídas do pipeline $currentOp
:
totalOperationTimeElapsedSecs
: tempo de operação decorrido em segundosremainingOperationTimeEstimatedSecs
: tempo restante estimado para a operação de refragmentação atual. É retornado como-1
quando uma nova operação de refragmentação é iniciada.Começando no:
MongoDB 5.0, mas antes do MongoDB 6.1, o
remainingOperationTimeEstimatedSecs
só está disponível em um shard de receptor durante uma operação de refragmentação.MongoDB 6.1,
remainingOperationTimeEstimatedSecs
também está disponível no coordenador durante uma operação de refragmentação.
A operação de refragmentação executa estas fases na ordem:
A fase do clonagem duplica os dados da collection atual.
A fase de atualização aplica quaisquer operações de gravação pendentes à collection refragmentada.
remainingOperationTimeEstimatedSecs
está definido para uma estimativa de tempo pessimista:A estimativa de tempo da fase de recuperação é definida como o tempo da fase de clonagem, que é um tempo relativamente longo.
Na prática, se houver apenas algumas operações de escrita pendentes, o tempo de fase de recuperação real é relativamente curto.
[ { shard: '<shard>', type: 'op', desc: 'ReshardingRecipientService | ReshardingDonorService | ReshardingCoordinatorService <reshardingUUID>', op: 'command', ns: '<database>.<collection>', originatingCommand: { reshardCollection: '<database>.<collection>', key: <shardkey>, unique: <boolean>, collation: { locale: 'simple' } }, totalOperationTimeElapsedSecs: <number>, remainingOperationTimeEstimatedSecs: <number>, ... }, ... ]
Conclua a operação de refragmentação.
Durante todo o processo de refragmentação, o tempo estimado para concluir a operação de refragmentação (remainingOperationTimeEstimatedSecs
) diminui. Quando o tempo estimado é inferior a dois segundos,a MongoDB bloqueia as gravações e conclui a operação de refragmentação. Até que o tempo estimado para concluir a operação de refragmentação seja inferior a dois segundos, a operação de refragmentação não bloqueia gravações por padrão. Durante o período em que as gravações são bloqueadas, seu aplicativo experimenta um aumento na latência.
Depois que o processo de refragmentação for concluído, o comando de refragmentação retornará ok: 1
.
{ ok: 1, '$clusterTime': { clusterTime: <timestamp>, signature: { hash: Binary(Buffer.from("0000000000000000000000000000000000000000", "hex"), 0), keyId: <number> } }, operationTime: <timestamp> }
Para ver se a operação de refragmentação foi concluída com sucesso, verifique a saída do método sh.status()
:
sh.status()
A saída do método sh.status()
contém uma subseção para o databases
. Se a refragmentação tiver sido concluída com êxito, a saída listará a nova chave de shard para a collection:
databases [ { database: { _id: '<database>', primary: '<shard>', partitioned: true, version: { uuid: <uuid>, timestamp: <timestamp>, lastMod: <number> } }, collections: { '<database>.<collection>': { shardKey: <shardkey>, unique: <boolean>, balancing: <boolean>, chunks: [], tags: [] } } } ... ]
Observação
Se a coleção refragmentada usar o Atlas Search, o índice de pesquisa ficará indisponível quando a operação de refragmentação for concluída. Você precisa refragmentar manualmente o índice de pesquisa assim que a operação de refragmentação for concluída.
Inicie o bloqueio das gravações com antecedência para forçar a conclusão da refragmentação
Você pode forçar manualmente a conclusão da operação de refragmentação emitindo o comando commitReshardCollection
. Isso é útil se a estimativa de tempo atual para concluir a operação de refragmentação for uma duração aceitável para que sua collection bloqueie gravações. O comando commitReshardCollection
bloqueia as gravações antecipadamente e força a conclusão da operação de refragmentação. O comando tem a seguinte sintaxe:
db.adminCommand({ commitReshardCollection: "<database>.<collection>" })
Abortar operação de refragmentação
Você pode cancelar a operação de refragmentação durante qualquer estágio da operação de refragmentação, mesmo após executar o commitReshardCollection
, até que os shards estejam totalmente atualizados.
Por exemplo, se remainingOperationTimeEstimatedSecs
não diminuir, você poderá cancelar a operação de refragmentação com o comando abortReshardCollection
:
db.adminCommand({ abortReshardCollection: "<database>.<collection>" })
Depois de cancelar a operação, você pode tentar novamente a operação de refragmentação em uma janela de tempo com menor volume de gravação. Se isso não for possível, adicione mais shards antes de tentar novamente.
Comportamento
Duração mínima de uma operação de refragmentação
A duração mínima de uma operação de refragmentação é sempre de cinco minutos.
Gravações repetíveis
As Retryable Writes iniciadas antes ou durante a refragmentação podem ser repetidas durante e após a collection ter sido refragmentada por até cinco minutos. Após cinco minutos, talvez você não consiga encontrar o resultado definitivo da gravação e as tentativas subsequentes de repetir a gravação falharão com o erro IncompleteTransactionHistory
.
Casos de erro
Failovers primários
Se ocorrer um failover primary em um shard de conjunto de réplicas ou servidor de configuração, a operação de refragmentação será cancelada.
Se uma operação de refragmentação for cancelada devido a um failover primary, execute o comando cleanupReshardCollection
antes de iniciar uma nova operação de refragmentação:
db.runCommand({ cleanupReshardCollection: "<database>.<collection>" })
Duplicate _id
Values
A operação de refragmentação falhará se _id
valores não forem globalmente exclusivos para evitar a corrupção dos dados da collection. Valores _id
duplicados também podem impedir a migração bem-sucedida de chunks. Se houver documentos com valores _id
duplicados, copie os dados de cada um deles em um novo documento e, em seguida, exclua os documentos duplicados.