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

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:

    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 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:

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

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>"
})

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.

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>"
})

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