MongoDB é um banco de dados NoSQL que utiliza documentos do tipo JSON com esquemas dinâmicos. Ao trabalhar com bancos de dados, é sempre bom ter um plano de contingência caso um de seus servidores de banco de dados falhe. Além disso, você pode reduzir as chances de isso acontecer utilizando uma ferramenta de gerenciamento interessante em seu site WordPress.

Por isso a utilidade de possuir muitas cópias de seus dados. Isso também reduz as latências de leitura. Ao mesmo tempo, ele pode melhorar a escalabilidade e a disponibilidade do banco de dados. É aqui que entra a replicação. Replicação é definida como a prática de sincronização de dados entre múltiplos bancos de dados.

Neste artigo, analisaremos vários aspectos relevantes da replicação do MongoDB, como suas funcionalidades e mecanismo, para citar alguns exemplos.

O que é replicação no MongoDB?

No MongoDB, conjuntos de réplicas (replica sets) realizam a replicação. Trata-se de um grupo de servidores que mantêm o mesmo conjunto de dados através da replicação. Você também pode utilizar a replicação do MongoDB como parte do balanceador de carga. Nesse caso, é possível distribuir as operações de escrita e leitura entre todas as instâncias, de acordo com a necessidade do caso de uso.

O que é um conjunto de réplicas MongoDB?

Cada instância do MongoDB que faz parte de um determinado conjunto de réplicas é um membro. Cada conjunto de réplicas precisa ter um membro principal e pelo menos um membro secundário.

O membro primário é o principal ponto de acesso para transações com o conjunto de réplicas. É também o único membro que pode aceitar operações de escrita. A réplica primeiro copia o oplog (registro de operações) do membro principal. Em seguida, ela repete as alterações registradas nos respectivos conjuntos de dados dos secundários. Portanto, cada conjunto de réplicas só pode ter um membro principal de cada vez. Vários membros primários que recebem operações de escrita podem causar conflitos de dados.

Normalmente, os aplicativos consultam apenas o membro primário para operações de escrita e leitura. Você pode projetar sua configuração para ler de um ou mais dos membros secundários. A transferência de dados assíncrona pode fazer com que leituras nos nós secundários sirvam dados antigos. Portanto, essa disposição não é ideal para todos os casos de uso.

Funcionalidades do conjunto de réplicas

O mecanismo automático de failover faz com que a réplica da MongoDB se diferencie da concorrência. Na ausência de um primário, uma eleição automatizada entre os secundários escolhe um novo primário.

Conjunto de réplicas MongoDB vs MongoDB Cluster

Um conjunto de réplicas MongoDB irá criar várias cópias do mesmo conjunto de dados através do conjunto de réplicas. O objetivo principal de um conjunto de réplicas é:

  • Oferecer uma solução de backup integrada
  • Aumentar a disponibilidade dos dados

Um cluster MongoDB é um jogo completamente diferente. Ele distribui os dados por vários nodes através de uma chave shard (shard key). Esse processo fragmenta os dados em várias partes chamadas de shards. Em seguida, cada shard é copiado para um node diferente. Um cluster visa suportar grandes conjuntos de dados e operações de alto rendimento, alcançando isso através do escalonamento horizontal da carga de trabalho. Isso permite que o sistema cresça de forma eficiente à medida que mais dados são adicionados e mais operações são realizadas.

Aqui está a diferença entre um conjunto de réplicas e um agrupamento, em termos leigos:

  • Um cluster distribui a carga de trabalho. Ele também armazena fragmentos de dados (shards) em muitos servidores.
  • Um conjunto de réplicas duplica completamente o conjunto de dados.

O MongoDB permite que você combine essas funcionalidades criando um cluster particionado. Aqui, você pode replicar cada shard para um servidor secundário. Isso permite que um shard ofereça alta redundância e disponibilidade de dados.

Manter e configurar um conjunto de réplicas pode ser tecnicamente desafiador e demorado. E encontrar o serviço de hospedagem certo? Isso é uma dor de cabeça totalmente diferente. Com tantas opções por aí, é fácil perder horas pesquisando em vez de construir seu negócio.

Aqui está uma breve explicação sobre uma ferramenta que faz tudo isso e muito mais, para que você possa continuar sendo bem-sucedido com seu serviço/produto.

A solução Hospedagem de Aplicativos da Kinsta, usada por mais de 55.000 desenvolvedores, permite que você esteja pronto para trabalhar em apenas 3 etapas simples. Se isso parece bom demais para ser verdade, aqui estão mais alguns benefícios de usar a Kinsta:

  • Aproveite o melhor desempenho com as conexões internas da Kinsta: Esqueça suas lutas com bancos de dados compartilhados. Mude para bancos de dados dedicados com conexões internas que não têm limite de contagem de consultas ou de linhas. Kinsta é mais rápido, mais seguro e não lhe cobra pela largura de banda/tráfego interno.
  • Um conjunto de recursos sob medida para desenvolvedores: Escale seu aplicativo na plataforma robusta que suporta Gmail, YouTube e Google Search. Fique tranquilo, você está em mãos seguras.
  • Desfrute de velocidades inigualáveis com um centro de dados da sua escolha: Escolha a região que funciona melhor para você e seus clientes. Com mais de 25 centros de dados à sua escolha, os 260+ PoPs da Kinsta garantem a máxima velocidade e uma presença global ao seu site.

Experimente a solução de hospedagem de aplicativos da Kinsta gratuitamente hoje mesmo!

Como funciona a replicação no MongoDB?

No MongoDB, você envia operações de escrita para o servidor primário (node). O servidor primário atribui as operações através dos servidores secundários, replicando os dados.

Ilustração do Processo de Replicação MongoDB
Ilustração do Processo de Replicação MongoDB (Fonte de Imagem: MongoDB)

Três tipos de Nodes MongoDB

Dos três tipos de nodes do MongoDB, dois já foram mencionados anteriormente: nodes primários e secundários. O terceiro tipo de node do MongoDB que se mostra útil durante a replicação é um árbitro. O node árbitro não possui uma cópia do conjunto de dados e não pode se tornar um primário. Dito isso, o árbitro participa das eleições para o primário.

Nós já mencionamos anteriormente o que acontece quando o node primário fica indisponível, mas e se os nodes secundários forem perdidos? Nesse cenário, o node primário passa a ser secundário e o banco de dados fica inacessível.

 

Eleição de membro

As eleições podem ocorrer nos seguintes cenários:

  • Inicialização de um conjunto de réplicas
  • Perda de conectividade com o node primário (que pode ser detectada por batimentos cardíacos)
  • Manutenção de um conjunto de réplicas usando os métodos rs.reconfig ou stepDown
  • Adicionando um novo node a um conjunto de réplicas existentes

Uma réplica pode possuir até 50 membros, mas só até 7 podem votar em qualquer eleição.

O tempo médio antes que um cluster eleja um novo primário não deve ultrapassar 12 segundos. O algoritmo de eleição tentará ter o secundário com a maior prioridade disponível. Ao mesmo tempo, os membros com um valor de prioridade de 0 não podem se tornar primários e não participam da eleição.

Node secundário tornando-se primário
Node secundário tornando-se primário (Fonte da imagem: Medium)

 

A preocupação com a escrita (Write Concern)

Para garantir a durabilidade, as operações de escrita possuem uma framework para copiar os dados em um número especificado de nodes. Você até pode oferecer feedback ao cliente com isso. Essa framework é também conhecida como “preocupação com a escrita” (“write concern”). Ela possui membros que carregam dados e que precisam reconhecer uma preocupação com a escrita antes que a operação seja considerada bem-sucedida. Geralmente, os conjuntos de réplicas têm um valor de 1 como preocupação com a escrita. Portanto, apenas o node primário deve reconhecer a escrita antes de retornar o reconhecimento da preocupação com a escrita.

Você também pode aumentar o número de membros necessários para reconhecer a operação de escrita. Não há limite para o número de membros que você pode ter. No entanto, se os números forem altos, é necessário lidar com alta latência. Isso ocorre porque o cliente precisa esperar pelo reconhecimento de todos os membros. Além disso, você pode definir a preocupação com a escrita da “maioria”. Isso calcula mais da metade dos membros após receber o reconhecimento deles.

Preferência de leitura

Para as operações de leitura, você pode mencionar a preferência de leitura que descreve como o banco de dados direciona a consulta para os membros do conjunto de réplicas. Geralmente, o node primário recebe a operação de leitura, mas o cliente pode mencionar uma preferência de leitura para enviar as operações de leitura para nodes secundários. Aqui estão as opções para a preferência de leitura:

  • primaryPreferred: Geralmente, as operações de leitura vêm do node primário, mas se ele não estiver disponível, os dados são obtidos dos nodes secundários.
  • primary: Todas as operações de leitura vêm do node primário.
  • secondary: Todas as operações de leitura são executadas pelos nodes secundários.
  • nearest: Aqui, as solicitações de leitura são roteadas para o node mais próximo que pode ser alcançado, o que pode ser detectado executando o comando de ping. O resultado das operações de leitura pode vir de qualquer membro do conjunto de réplicas, independentemente de ser o primário ou o secundário.
  • secondaryPreferred: Aqui, a maioria das operações de leitura vem dos nodes secundários, mas se nenhum deles estiver disponível, os dados são obtidos do node primário.

Sincronização de dados do conjunto de replicação

Para manter cópias atualizadas do conjunto de dados compartilhados, os membros secundários de um conjunto de réplicas replicam ou sincronizam dados de outros membros.

O MongoDB utiliza duas formas de sincronização de dados. A primeira é a sincronização inicial (initial sync), que popula novos membros com o conjunto completo de dados. A segunda é a replicação (replication), que executa alterações contínuas no conjunto completo de dados para manter todos os membros atualizados.

Sincronização inicial

Durante a sincronização inicial, um node secundário executa o comando de sincronização inicial init sync para sincronizar todos os dados do node primário para outro node secundário que contém os dados mais recentes. Portanto, o node secundário utiliza consistentemente a funcionalidade tailable cursor para consultar as entradas mais recentes do oplog na coleção local.oplog.rs do node primário e aplica essas operações dentro dessas entradas do oplog.

A partir do MongoDB 5.2, sincronizações iniciais podem ser baseadas em cópia de arquivos ou lógicas.

Sincronização lógica

Quando você executa uma sincronia lógica, o MongoDB:

  1. Desenvolve todos os índices de coleção à medida que os documentos são copiados para cada coleção.
  2. Duplica todos os bancos de dados, exceto o banco de dados local. mongod examina cada coleção em todos os bancos de dados de origem e insere todos os dados em suas duplicatas dessas coleções.
  3. Executa todas as alterações no conjunto de dados. Ao aproveitar o oplog da fonte, o mongod atualiza seu conjunto de dados para retratar o estado atual do conjunto de réplicas.
  4. Extrai registros de oplog recém-adicionados durante a cópia de dados. Certifique-se de que o membro de destino tenha espaço em disco suficiente dentro do banco de dados local para armazenar tentativamente esses registros de oplog durante a duração dessa etapa de cópia de dados.

Quando a sincronização inicial é concluída, o membro passa de STARTUP2 para SECONDARY .

Sincronização inicial baseada em cópia de arquivo

Logo de cara, você só pode executar isso se você usar o MongoDB Enterprise. Este processo executa a sincronização inicial duplicando e movendo os arquivos no sistema de arquivos. Este método de sincronização pode ser mais rápido que a sincronização inicial lógica em alguns casos. Tenha em mente que a sincronização inicial baseada em cópia de arquivo pode levar a contagens imprecisas se você executar o método count() sem um predicado de consulta.

Mas, este método também tem sua parcela de limitações:

  • Durante uma sincronização inicial baseada em cópia de arquivo, você não pode escrever no banco de dados local do membro que está sendo sincronizado. Você também não pode executar um backup do membro que está sendo sincronizado ou do membro que está sendo sincronizado.
  • Ao aproveitar o mecanismo de armazenamento criptografado, o MongoDB usa a chave de origem para criptografar o destino.
  • Você só pode executar uma sincronização inicial de um determinado membro de cada vez.

Replicação

Os membros secundários replicam os dados consistentemente após a sincronização inicial. Os membros secundários duplicarão o oplog da sua sincronização a partir da fonte e executarão estas operações em um processo assíncrono.

Os secundários são capazes de modificar automaticamente sua sincronização a partir da fonte conforme necessário, com base nas alterações no tempo de ping e estado da replicação dos outros membros.

Replicação em fluxo contínuo

A partir do MongoDB 4.4, a sincronização a partir de fontes envia um fluxo contínuo de entradas de oplog para seus secundários de sincronização. A replicação em fluxo contínuo reduz o atraso de replicação em redes de alta carga e de alta latência. Ela também pode:

  • Diminuir o risco de perder operações de escrita com w:1 devido ao failover primário.
  • Diminuir a impraticabilidade para leituras de secundárias.
  • Reduzir a latência nas operações de escrita com w:“majority” e w:>1. Em resumo, qualquer preocupação de escrita que precise esperar pela replicação.
Replicação multithreaded

O MongoDB costumava realizar operações de escrita em lotes por meio de várias threads para melhorar a concorrência. O MongoDB agrupa os lotes por ID de documento enquanto aplica cada grupo de operações com uma thread diferente.

O MongoDB sempre executa operações de escrita em um determinado documento na sua ordem original de escrita. Isso mudou no MongoDB 4.0.

A partir do MongoDB 4.0, operações de leitura direcionadas a secundários e configuradas com um nível de preocupação de leitura de “majority” ou “local” agora lerão de um snapshot WiredTiger dos dados, se a leitura ocorrer em um secundário onde os lotes de replicação estão sendo aplicados. Ler de um snapshot garante uma visualização consistente dos dados e permite que a leitura ocorra simultaneamente com a replicação em andamento sem precisar de um bloqueio.

Portanto, leituras secundárias que necessitam desses níveis de preocupação de leitura não precisam mais esperar que os lotes de replicação sejam aplicados e podem ser tratadas conforme são recebidas.

Como criar um conjunto de réplicas MongoDB

Como mencionado anteriormente, o MongoDB trata a replicação através de réplicas. Nas próximas seções, vamos destacar alguns métodos que você pode usar para criar réplicas para o seu caso de uso.

Método 1: Criando um novo conjunto de réplicas MongoDB no Ubuntu

Antes de começarmos, você precisará garantir que você tem pelo menos três servidores rodando no Ubuntu 20.04, com o MongoDB instalado em cada servidor.

Para montar um conjunto de réplicas, é essencial fornecer um endereço onde cada membro do conjunto de réplicas possa ser alcançado por outros no conjunto. Neste caso, mantemos três membros no conjunto. Embora possamos usar endereços IP, isso não é recomendado, pois os endereços podem mudar inesperadamente. Uma alternativa melhor pode ser usar os nomes de hosts DNS lógicos ao configurar os conjuntos de réplicas.

Podemos fazer isso configurando o subdomínio para cada membro replicado. Embora isso possa ser ideal para um ambiente de produção, esta seção irá delinear como configurar a resolução DNS editando os arquivos dos respectivos hosts de cada servidor. Este arquivo nos permite atribuir hostname legíveis a endereços IP numéricos. Assim, se em algum evento o seu endereço IP mudar, tudo que você precisa fazer é atualizar os arquivos de hosts nos três servidores, em vez de reconfigurar o conjunto de réplicas do zero!

Na maioria das vezes, hosts é armazenado no diretório /etc/. Repita os comandos abaixo para cada um de seus três servidores:

sudo nano /etc/hosts

No comando acima, estamos usando o nano como nosso editor de texto, no entanto, você pode usar qualquer editor de texto que preferir. Após as primeiras linhas que configuram o localhost, adicione uma entrada para cada membro do conjunto de réplicas. Essas entradas têm a forma de um endereço IP seguido pelo nome legível da sua escolha. Embora você possa nomeá-los como preferir, certifique-se de ser descritivo para poder diferenciar entre cada membro. Para este tutorial, usaremos os seguintes hostname:

  • mongo0.replset.membro
  • mongo1.replset.membro
  • mongo2.replset.membro

Usando esses hostnames, seus arquivos /etc/hosts ficariam semelhantes às linhas destacadas a seguir:

Ilustração dos Hostnames.
Ilustração dos Hostnames.

Salve e feche o arquivo.

Após configurar a resolução DNS para o conjunto de réplicas, precisamos atualizar as regras do firewall para permitir que eles se comuniquem uns com os outros. Execute o seguinte comando ufw no mongo0 para fornecer acesso mongo1 à porta 27017 no mongo0:

sudo ufw allow from mongo1_server_ip to any port 27017

No lugar do parâmetro mongo1_server_ip, digite o endereço IP real do seu servidor mongo1. Além disso, se você atualizou a instância do MongoDB neste servidor para usar uma porta diferente do padrão, certifique-se de alterar o número 27017 para refletir a porta que sua instância do MongoDB está usando.

Agora, adicione outra regra de firewall para dar ao mongo2 acesso à mesma porta:

sudo ufw allow from mongo2_server_ip to any port 27017

No lugar do parâmetro mongo2_server_ip, digite o endereço IP real do seu servidor mongo2. Depois, atualize as regras de firewall para os seus outros dois servidores. Execute os seguintes comandos no servidor mongo1, certificando-se de alterar os endereços IP no lugar do parâmetro server_ip para refletir os do mongo0 e mongo2, respectivamente:

sudo ufw allow from mongo0_server_ip to any port 27017
sudo ufw allow from mongo2_server_ip to any port 27017

Finalmente, execute estes dois comandos em mongo2. Mais uma vez, certifique-se de digitar os endereços IP corretos para cada servidor:

sudo ufw allow from mongo0_server_ip to any port 27017
sudo ufw allow from mongo1_server_ip to any port 27017

Seu próximo passo é atualizar o arquivo de configuração de cada instância MongoDB para permitir conexões externas. Para permitir isso, você precisa modificar o arquivo de configuração em cada servidor para refletir o endereço IP e indicar o conjunto de réplicas. Enquanto você pode usar qualquer editor de texto preferido, estamos usando o editor de texto nano mais uma vez. Vamos fazer as seguintes modificações em cada arquivo mongod.conf.

Em mongo0:

# network interfaces
net:
port: 27017
bindIp: 127.0.0.1,mongo0.replset.member# replica set
replication:
replSetName: "rs0"

Em mongo1:

# network interfaces
net:
port: 27017
bindIp: 127.0.0.1,mongo1.replset.member
replication:
replSetName: "rs0"

Em mongo2:

# network interfaces
net:
port: 27017
bindIp: 127.0.0.1,mongo2.replset.member
replication:
replSetName: "rs0"
sudo systemctl restart mongod

Com isso, você habilitou a replicação para cada instância MongoDB do servidor.

Agora você pode inicializar a réplica definida usando o método rs.initiate(). Este método só é necessário para ser executado em uma única instância MongoDB no conjunto de réplicas. Certifique-se de que o nome do conjunto de réplicas e o membro correspondem às configurações que você fez em cada arquivo de configuração anteriormente.

rs.initiate(
  {
    _id: "rs0",
    members: [
      { _id: 0, host: "mongo0.replset.member" },
      { _id: 1, host: "mongo1.replset.member" },
      { _id: 2, host: "mongo2.replset.member" }
    ]
  }
)

Caso o método retorne “ok”: 1 na saída, significa que o conjunto de réplicas foi iniciado corretamente. Abaixo está um exemplo de como a saída deve ser:

 "ok": 1,
  "$clusterTime": {
    "clusterTime": Timestamp(1612389071, 1),
    "signature": {
      "hash": BinData(0, "AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
      "keyId": NumberLong(0)
    }
  },
  "operationTime": Timestamp(1612389071, 1)
}

Desativando o servidor MongoDB

Você pode desativar um servidor MongoDB usando o método db.shutdownServer(). Abaixo está a sintaxe para o mesmo. Ambos force e timeoutsecs são parâmetros opcionais.

db.shutdownServer({
  force: <boolean>,
  timeoutSecs: <int>
})

Este método pode falhar se o membro do conjunto de réplicas mongod executar certas operações à medida que o índice é construído. Para interromper as operações e forçar o membro a desativar, você pode inserir o parâmetro booleano force para true.

Reinicie o MongoDB com –replSet

Para redefinir a configuração, certifique-se de que cada node no seu conjunto de réplicas esteja parado. Em seguida, exclua o banco de dados local para cada node. Inicie novamente usando a opção –replSete execute o comando rs.initiate() apenas em uma instância mongod do conjunto de réplicas.

mongod --replSet "rs0"

rs.initiate() pode pegar uma réplica opcional do documento de configuração do conjunto, ou seja:

  • A opção Replication.replSetName ou a opção —replSet para especificar o nome do conjunto de réplicas no campo _id.
  • A array dos membros, que contém um documento para cada membro do conjunto de réplicas.

O método rs.initiate() desencadeia uma eleição e elege um dos membros para ser o primário.

Adicionando membros ao conjunto de réplicas

Para adicionar membros ao conjunto, inicie instâncias mongod em várias máquinas. Em seguida, inicie um cliente mongo e use o comando rs.add().

O comando rs.add() tem a seguinte sintaxe básica:

rs.add(HOST_NAME:PORT)

Por exemplo,

Assuma que mongo1 é sua instância mongod, e que está ouvindo na porta 27017. Use o comando do cliente Mongo rs.add() para adicionar esta instância ao conjunto de réplicas.

rs.add("mongo1:27017")

Somente depois que você estiver conectado ao node primário você pode adicionar uma instância mongod ao conjunto de réplicas. Para verificar se você está conectado ao node primário, use o comando db.isMaster().

Removendo membros

Para remover um membro, podemos usar rs.remove().

Para fazer isso, primeiro, encerre a instância mongod que você deseja remover, usando o método db.shutdownServer() que discutimos acima.

Em seguida, conecte-se ao primário atual do conjunto de réplicas. Para determinar o primário atual, use db.hello() enquanto estiver conectado a qualquer membro do conjunto de réplicas. Depois de determinar o primário, execute um dos seguintes comandos:

rs.remove("mongodb-node-04:27017")
rs.remove("mongodb-node-04")
A imagem acima mostra que o node foi removido com sucesso do conjunto de réplicas.
A imagem acima mostra que o node foi removido com sucesso do conjunto de réplicas. (Fonte da imagem: Bmc)

Se o conjunto de réplicas precisar eleger um novo node primário, o MongoDB poderá desconectar brevemente o shell. Nesse cenário, ele se reconectará automaticamente novamente. Além disso, pode ser exibido um erro DBClientCursor::init call(), mesmo que o comando tenha sucesso.

Método 2: Configuração de um conjunto de réplicas MongoDB para implantação e teste

Em geral, você pode configurar conjuntos de réplicas para testes com o RBAC ativado ou desativado. Neste método, estaremos configurando conjuntos de réplicas com o controle de acesso desabilitado para implementá-lo em um ambiente de teste.

Primeiro, crie diretórios para todas as instâncias que fazem parte do conjunto de réplicas usando o seguinte comando:

mkdir -p /srv/mongodb/replicaset0-0  /srv/mongodb/replicaset0-1 /srv/mongodb/replicaset0-2

Este comando irá criar diretórios para três instâncias MongoDB replicaset0-0, replicaset0-1, e replicaset0-2. Agora, inicie as instâncias do MongoDB para cada uma delas usando o seguinte conjunto de comandos:

Para o Servidor 1:

mongod --replSet replicaset --port 27017 --bind_ip localhost,<hostname(s)|ip address(es)> --dbpath /srv/mongodb/replicaset0-0  --oplogSize 128

Para o Servidor 2:

mongod --replSet replicaset --port 27018 --bind_ip localhost,<hostname(s)|ip address(es)> --dbpath /srv/mongodb/replicaset0-0  --oplogSize 128

Para o Servidor 3:

mongod --replSet replicaset --port 27019 --bind_ip localhost,<hostname(s)|ip address(es)> --dbpath /srv/mongodb/replicaset0-0  --oplogSize 128

O parâmetro –oplogSize é usado para evitar que a máquina fique sobrecarregada durante a fase de teste. Ele ajuda a reduzir a quantidade de espaço em disco que cada disco consome.

Agora, conecte-se a uma das instâncias usando o shell do Mongo, conectando-se pelo número da porta abaixo.

mongo --port 27017

Podemos usar o comando rs.initiate() para iniciar o processo de replicação. Você terá que substituir o parâmetro hostname pelo nome do seu sistema.

rs conf = {

  _id: "replicaset0",

  members: [

    {  _id: 0,  host: "<hostname>:27017},

    {  _id: 1,  host: "<hostname>:27018"},

    {  _id: 2,  host: "<hostname>:27019"}

   ] }

Agora você pode passar o arquivo objeto de configuração como parâmetro para o comando start e usá-lo da seguinte forma:

rs.initiate(rsconf)

E pronto! Você criou com sucesso uma réplica do MongoDB para fins de desenvolvimento e testes.

Método 3: Transformando uma instância autônoma em um conjunto de réplicas MongoDB

MongoDB permite que seus usuários transformem suas instâncias isoladas em conjuntos de réplicas. Enquanto as instâncias autônomas são usadas principalmente para a fase de teste e desenvolvimento, os conjuntos de réplicas são parte do ambiente de produção.

Para começar, vamos encerrar à nossa instância mongod usando o seguinte comando:

db.adminCommand({"shutdown":"1"})

Reinicie sua instância usando o parâmetro –repelSet em seu comando para especificar o conjunto de réplicas que você vai usar:

mongod --port 27017 – dbpath /var/lib/mongodb  --replSet replicaSet1 --bind_ip localhost,<hostname(s)|ip address(es)>

Você deve especificar o nome do seu servidor com o endereço único no comando.

Conecte a shell com sua instância MongoDB e use o comando initiate para iniciar o processo de replicação e converter com sucesso a instância para um conjunto de réplicas. Você pode executar todas as operações básicas como adicionar ou remover uma instância usando os seguintes comandos:

rs.add(“<host_name:port>”)
rs.remove(“host-name”)

Adicionalmente, você pode verificar o status do seu conjunto de réplicas MongoDB usando os comandos rs.status() e rs.conf().

Método 4: Atlas MongoDB – uma alternativa mais simples

A replicação e o sharding podem trabalhar juntos para formar algo chamado um cluster particionado (sharded cluster). Embora a configuração e a instalação possam ser bastante demoradas, embora diretas, o MongoDB Atlas é uma alternativa melhor do que os métodos mencionados anteriormente.

Ele automatiza seus conjuntos de réplicas, tornando o processo fácil de implementar. Ele pode implementar conjuntos de réplicas globalmente fragmentadas com poucos cliques, permitindo a recuperação de desastres, gerenciamento mais fácil, localização de dados e implementações em várias regiões.

No Atlas MongoDB, precisamos criar clusters – eles podem ser um conjunto de réplicas, ou um sharded cluster. Para um determinado projeto, o número de nodes em um cluster em outras regiões é limitado a um total de 40.

Isso exclui os clusters gratuitos ou compartilhados e as regiões do Google Cloud que se comunicam entre si. O número total de nodes entre quaisquer duas regiões deve atender a essa restrição. Por exemplo, se houver um projeto no qual:

  • A Região A tem 15 nodes
  • A Região B tem 25 nodes
  • A Região C tem 10 nodes

Só podemos alocar mais 5 nodes para a região C como,

  1. Região A+ Região B = 40; atende a restrição de 40 sendo o número máximo de nodes permitido.
  2. Região B+ Região C = 25+10+5 (Nodes adicionais alocados para C) = 40; atende à restrição de 40 sendo o número máximo de nodes permitido.
  3. Região A+ Região C = 15+10+5 (Nodes adicionais atribuídos a C) = 30; atende à restrição de 40 sendo o número máximo de nodes permitido.

Se alocamos mais 10 nodes para a região C, fazendo com que a região C tenha 20 nodes, então a Região B + Região C = 45 nodes. Isso excederia a restrição dada, então você pode não ser capaz de criar um cluster multi-região.

Quando você cria um cluster, a Atlas cria um contêiner de rede no projeto para o provedor da nuvem se ele não estivesse lá anteriormente. Para criar um cluster de réplicas no MongoDB Atlas, execute o seguinte comando no Atlas CLI:

atlas clusters create [name] [options]

Certifique-se de dar um nome descritivo de cluster, pois ele não pode ser alterado após a criação do cluster. O argumento pode conter letras ASCII, números e hifens.

Existem várias opções disponíveis para criação de clusters no MongoDB com base em suas necessidades. Por exemplo, se você quiser um backup em nuvem contínuo para o seu cluster, configure --backup para true.

Lidando com atrasos na replicação

O atraso na replicação pode ser bastante perturbador. É um atraso entre uma operação no primário e o aplicativo dessa operação a partir do oplog no secundário. Se o seu negócio lida com grandes conjuntos de dados, é esperado um atraso dentro de um certo limite. No entanto, às vezes fatores externos também podem contribuir e aumentar o atraso. Para se beneficiar de uma replicação atualizada, certifique-se de que:

  1. Você direcione o tráfego da sua rede com uma largura de banda estável e suficiente. A latência da rede desempenha um papel enorme em afetar sua replicação, e se a rede for insuficiente para atender às necessidades do processo de replicação, haverá atrasos na replicação de dados em todo o conjunto de réplicas.
  2. Você tenha um throughput de disco suficiente. Se o sistema de arquivos e o dispositivo de disco no secundário não conseguirem descarregar os dados para o disco tão rapidamente quanto o primário, então o secundário terá dificuldade em acompanhar. Assim, os nodes secundários processam as consultas de escrita mais lentamente do que o node primário. Este é um problema comum na maioria dos sistemas multi-inquilino, incluindo instâncias virtualizadas e implantações em larga escala.
  3. Você solicite um reconhecimento de escrita com write concern após um intervalo para dar a oportunidade aos secundários de acompanhar o primário, especialmente quando você quer realizar uma operação de carga em massa ou ingestão de dados que requer um grande número de escritas no primário. Os secundários não serão capazes de ler o oplog rápido o suficiente para acompanhar as mudanças; particularmente com write concern não reconhecidos.
  4. Você identifique as tarefas em segundo plano em execução. Certas tarefas, como jobs cron, atualizações de servidor e verificações de segurança, podem ter efeitos inesperados no uso da rede ou do disco, causando atrasos no processo de replicação.

Se você não tem certeza se há um atraso de replicação em seu aplicativo, não se preocupe – a próxima seção discutirá estratégias de resolução de problemas!

 

Solucionando problemas em conjuntos de réplicas MongoDB

Você configurou com sucesso seus conjuntos de réplicas, mas você nota que seus dados são inconsistentes entre os servidores. Isso é muito alarmante para grandes empresas, no entanto, com métodos rápidos de solução de problemas, você pode encontrar a causa ou mesmo corrigir o problema! Abaixo estão algumas estratégias comuns para a solução de problemas de implantação de réplicas que podem ser úteis:

Verifique o status das réplicas

Podemos verificar o status atual do conjunto de réplicas e o status de cada membro executando o seguinte comando em uma sessão mongosh que está conectada ao conjunto de réplicas primárias.

 rs.status()

Confira o atraso de replicação

Como discutido anteriormente, o atraso na replicação pode ser um problema sério, pois torna os membros “atrasados” inelegíveis para se tornarem rapidamente primários e aumenta a possibilidade de que as operações de leitura distribuídas sejam inconsistentes. Podemos verificar o comprimento atual do atraso de replicação usando o seguinte comando:

rs.printSecondaryReplicationInfo()

Isso retorna o valor syncedTo que é o tempo em que a última entrada oplog foi escrita para o secundário para cada membro. Aqui está um exemplo para demonstrar o mesmo:

source: m1.example.net:27017
    syncedTo: Mon Oct 10 2022 10:19:35 GMT-0400 (EDT)
    0 secs (0 hrs) behind the primary
source: m2.example.net:27017
    syncedTo: Mon Oct 10 2022 10:19:35 GMT-0400 (EDT)
    0 secs (0 hrs) behind the primary

Um membro atrasado pode aparecer como 0 segundos atrás do primário quando o período de inatividade no primário é maior que o valor members[n].secondaryDelaySecs.

Testando conexões entre todos os membros

Cada membro de um conjunto de réplicas deve ser capaz de se conectar com todos os outros membros. Certifique-se sempre de verificar as conexões em ambas as direções. Na maioria das vezes, configurações de firewall ou topologias de rede impedem a conectividade normal e necessária que pode bloquear a replicação.

Por exemplo, vamos supor que a instância mongod vincula tanto ao localhost quanto ao hostname ‘ExampleHostname’ que está associado ao endereço IP 198.41.110.1:

mongod --bind_ip localhost, ExampleHostname

Para conectar-se a esta instância, os clientes remotos devem especificar o nome da máquina ou o endereço IP:

mongosh --host ExampleHostname
mongosh --host 198.41.110.1

Caso um conjunto de réplicas consista em três membros, m1, m2 e m3, usando a porta padrão 27017, você deve testar a conexão da seguinte forma:

No m1:

mongosh --host m2 --port 27017
mongosh --host m3 --port 27017

Em m2:

mongosh --host m1 --port 27017
mongosh --host m3 --port 27017

Em m3:

mongosh --host m1 --port 27017
mongosh --host m2 --port 27017

Caso qualquer conexão em qualquer direção falhar, você terá que verificar a configuração do seu firewall e reconfigurá-lo para permitir as conexões.

Garantindo comunicações seguras com autenticação keyfile

Por padrão, a autenticação por keyfile no MongoDB utiliza o mecanismo de autenticação SCRAM (Salted Challenge Response Authentication Mechanism). Para fazer isso, o MongoDB deve ler e validar as credenciais fornecidas pelo usuário, que incluem uma combinação de nome de usuário, senha e banco de dados de autenticação que a instância específica do MongoDB está ciente. Esse é exatamente o mecanismo utilizado para autenticar os usuários que fornecem uma senha ao se conectar ao banco de dados.

Quando você habilita a autenticação no MongoDB, o Role-Based Access Control (RBAC) é automaticamente habilitado para o conjunto de réplicas, e o usuário recebe uma ou mais funções que determinam seu acesso aos recursos do banco de dados. Quando o RBAC é habilitado, isso significa que somente o usuário válido do Mongo autenticado com os privilégios apropriados seria capaz de acessar os recursos no sistema.

O keyfile age como uma senha compartilhada para cada membro do cluster. Isso permite que cada instância mongod no conjunto de réplicas utilize o conteúdo do arquivo de chaves como senha compartilhada para autenticar outros membros na distribuição.

Somente as instâncias do “mongod” com o keyfile correto podem ingressar no conjunto de réplicas. O tamanho de uma chave deve estar entre 6 e 1024 caracteres e só pode conter caracteres no conjunto de caracteres base64. Por favor, observe que o MongoDB remove os caracteres de espaço em branco ao ler as chaves.

Você pode gerar um keyfile usando vários métodos. Neste tutorial, usamos openssl para gerar uma cadeia complexa de caracteres aleatórios 1024 para usar como uma senha compartilhada. Ele então usa chmod para mudar as permissões dos arquivos para fornecer permissões de leitura somente para o proprietário do arquivo. Evite armazenar o arquivo chave em mídias de armazenamento que podem ser facilmente desconectadas do hardware que hospeda as instâncias mongod, como um drive USB ou um dispositivo de armazenamento conectado à rede. Abaixo está o comando para gerar um arquivo de chave:

openssl rand -base64 756 > <path-to-keyfile>
chmod 400 <path-to-keyfile>

Em seguida, copie o arquivo de chave (keyfile) para cada membro do conjunto de réplicas. Certifique-se de que o usuário que executa as instâncias do “mongod” é o proprietário do arquivo e tem acesso ao keyfile. Após ter feito isso, desative todos os membros do conjunto de réplicas, começando pelos secundários. Depois que todos os secundários estiverem off-line, você pode prosseguir e desativar o primário. É essencial seguir essa ordem para evitar possíveis reversões (rollbacks). Agora, desative a instância do “mongod” executando o seguinte comando:

use admin
db.shutdownServer()

Após o comando ser executado, todos os membros do conjunto de réplicas estarão off-line. Agora, reinicie cada membro do conjunto de réplicas com o controle de acesso habilitado.

Para cada membro do conjunto de réplicas, inicie a instância mongod com a configuração do arquivo de configuração security.keyFile ou com a opção de linha de comando --keyFile.

Caso estiver usando um arquivo de configuração, defina

  • security.keyFile para o caminho do keyfile, e
  • replication.replSetName ao nome da réplica do conjunto.
security:
  keyFile: <path-to-keyfile>
replication:
  replSetName: <replicaSetName>
net:
   bindIp: localhost,<hostname(s)|ip address(es)>

Inicie a instância mongod usando o arquivo de configuração:

mongod --config <path-to-config-file>

Caso você esteja usando as opções de linha de comando, inicie a instância mongod com as seguintes opções:

  • –keyFile definido para o caminho do arquivo-chave, e
  • –replSet ajustado ao nome da réplica do conjunto.
mongod --keyFile <path-to-keyfile> --replSet <replicaSetName> --bind_ip localhost,<hostname(s)|ip address(es)>

Você pode incluir opções adicionais conforme necessário para à sua configuração. Por exemplo, se desejar que clientes remotos se conectem ao seu ambiente ou se os membros do seu ambiente são executados em hosts diferentes, especifique o –bind_ip. Para obter mais informações, consulte as Mudanças na Compatibilidade Localhost Binding.

Em seguida, conecte-se a um membro do conjunto de réplicas pela interface local (localhost). É necessário executar o “mongosh” na mesma máquina física em que a instância do “mongod” está sendo executada. Esta interface só está disponível quando nenhum usuário foi criado para a implantação e fecha automaticamente após a criação do primeiro usuário.

Então iniciamos o conjunto de réplicas. A partir de mongosh, execute o método rs.initiate():

rs.initiate(
  {
    _id: "myReplSet",
    members: [
      { _id: 0, host: "mongo1:27017" },
      { _id: 1, host: "mongo2:27017" },
      { _id: 2, host: "mongo3:27017" }
    ]
  }
)

Como discutido anteriormente, este método elege um dos membros para ser o membro primário do conjunto de réplicas. Para localizar o membro principal, use rs.status(). Conecte-se ao membro primário antes de continuar.

Agora, crie o administrador do usuário. Você pode adicionar um usuário usando o método db.createUser(). Certifique-se de que o usuário deve ter pelo menos a função userAdminAnyDatabase no banco de dados do administrador.

O exemplo a seguir cria o usuário ‘batman’ com a função userAdminAnyDatabase no banco de dados do administrador:

admin = db.getSiblingDB("admin")
admin.createUser(
  {
    user: "batman",
    pwd: passwordPrompt(), // or cleartext password
    roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
  }
)

Digite a senha criada anteriormente quando solicitado.

Em seguida, você deve autenticar-se como administrador do usuário. Para fazer isso, use db.auth() para autenticar. Por exemplo:

db.getSiblingDB(“admin”).auth(“batman”, passwordPrompt()) // ou cleartext password

Alternativamente, você pode conectar uma nova instância mongosh ao membro do conjunto primário de réplicas usando os parâmetros -u <username>, -p <password> e --authenticationDatabase.

mongosh -u "batman" -p  --authenticationDatabase "admin"

Mesmo se você não especificar a senha no campo de linha de comando -p, mongosh solicita a senha.

Finalmente, crie o administrador do cluster. A função clusterAdmin dá acesso às operações de replicação, tais como a configuração do conjunto de réplicas.

Vamos criar um usuário administrador de cluster e atribuir a função clusterAdmin no banco de dados do administrador:

db.getSiblingDB("admin").createUser(
  {
    "user": "robin",
    "pwd": passwordPrompt(),     // or cleartext password
    roles: [ { "role" : "clusterAdmin", "db" : "admin" } ]
  }
)

Digite a senha quando solicitado.

Se desejar, você pode criar usuários adicionais para permitir que clientes interajam com o conjunto de réplicas.

E pronto! Você habilitou com sucesso a autenticação por chave (keyfile authentication)!

Resumo

Replicação tem sido um requisito essencial quando se trata de bancos de dados, especialmente à medida que mais empresas expandem suas operações. Ela melhora significativamente o desempenho, a segurança dos dados e a disponibilidade do sistema. Falando em desempenho, é fundamental monitorar problemas de desempenho em seu banco de dados WordPress e corrigi-los rapidamente, por exemplo, utilizando ferramentas como Kinsta APM, Jetpack e Freshping, apenas para citar algumas.

A replicação ajuda a garantir a proteção dos dados em vários servidores e evita que seus servidores sofram com longos períodos de inatividade (ou pior – perda completa de dados). Neste artigo, abordamos a criação de um conjunto de réplicas e algumas dicas de solução de problemas, juntamente com a importância da replicação. Você usa a replicação do MongoDB para o seu negócio e tem sido útil para você? Deixe-nos saber na seção de comentários abaixo!

Jeremy Holcombe Kinsta

Content & Marketing Editor at Kinsta, WordPress Web Developer, and Content Writer. Outside of all things WordPress, I enjoy the beach, golf, and movies. I also have tall people problems ;).