Menu Docs
Página inicial do Docs
/
Manual do MongoDB
/ / /

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
  • Erro de Case
  • 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 query 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 shard de uma collection para mudar a distribuição de seus dados em um cluster.

A partir do MongoDB 8.0, você pode refragmentar uma coleção na mesma chave de fragmento, permitindo que você redistribua dados para incluir novos fragmentos ou para zonas diferentes sem alterar sua chave de fragmento.

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.

Antes de refragmentar sua collection, certifique-se de atender aos seguintes requisitos:

  • Seu aplicação pode tolerar um período de dois segundos em que a collection afetada bloqueia as gravações. Durante o período em que as gravações são bloqueadas, seu aplicação experimenta um aumento na latência.

    Se sua carga de trabalho não tolerar esse requisito, considere ajustar sua chave de fragmento.

  • Seu banco de dados atende aos seguintes requisitos de recursos:

    • Certifique-se de que o espaço de armazenamento disponível em cada fragmento em que a coleção será distribuída seja pelo menos duas vezes o tamanho da coleção que você deseja refragmentar e seu tamanho de índice total, dividido pelo número de fragmentos.

      storage_req = ( ( collection_storage_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.

    • Certifique-se de que sua capacidade de E/S esteja abaixo de 50%.

    • 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 demora mais que o esperado

    Se o seu aplicação tiver períodos com menos tráfego, execute esta operação na coleção 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:

    1. Pare seu aplicativo.

    2. Reescreva seu aplicação para usar a nova chave de shard.

    3. Aguarde até que a refragmentação seja concluída. Para monitorar o processo de refragmentação, use o estágio de pipeline $currentOp .

    4. 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.

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.

1

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.

2

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 segundos

  • remainingOperationTimeEstimatedSecs: 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 7.0, remainingOperationTimeEstimatedSecs só está disponível em um shard de destinatário durante uma operação de refragmentação.

    • MongoDB 7.0, 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:

    1. A fase do clonagem duplica os dados da collection atual.

    2. 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>,
...
},
...
]
3

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>',
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.

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 durante a seção crítica e força a conclusão da operação de refragmentação. O comando tem a seguinte sintaxe:

db.adminCommand({
commitReshardCollection: "<database>.<collection>"
})

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.

A duração mínima de uma operação de refragmentação é sempre de cinco minutos.

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.

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.

Voltar

Refinar uma chave de fragmento