Orientações para Resiliência do Atlas
Nesta página
- Recursos para Resiliência do Atlas
- Replicação de banco de dados
- Implantações de autocura
- Tempo de atividade da janela de manutenção
- Monitoramento
- Teste de resiliência do sistema
- Salvaguardas de encerramento de cluster
- Backups de banco de dados
- Recomendações para Resiliência do Atlas
- Use o MongoDB 8.0 ou posterior
- Conectando seu Aplicativo ao Atlas
- Considerações sobre pool de conexões para aplicativos de alto desempenho
- Tamanho mínimo e máximo do pool de conexões
- Tempo limite da consulta
- Leituras e gravações de banco de dados repetíveis
- Configurar write and read concerns
- Isolar o impacto de collections ativas e não fragmentadas
- Recuperação de desastres
- Aplicação de exemplo resiliente
O MongoDB Atlas é um banco de dados de alto desempenho projetado para manter o tempo de atividade, independentemente de interrupções de infraestrutura, manutenção de sistemas e muito mais. Use a orientação nesta página para planejar configurações para maximizar a resiliência do seu aplicação e banco de dados.
Recursos para Resiliência do Atlas
Replicação de banco de dados
Os Atlas clusters consistem em um conjunto de réplicas com um mínimo de três nós, e você pode aumentar a contagem de nós para qualquer número ímpar de nós necessários. O Atlas primeiro grava dados de seu aplicação em um nó primário e, em seguida, o Atlas replica e armazena de forma incremental esses dados em todos os nós secundários dentro do cluster. Para controlar a durabilidade do armazenamento de dados, você pode ajustar a preocupação de gravação do código do aplicação para concluir a gravação somente depois que um determinado número de secundários tiver confirmado a gravação. Para saber mais, consulte Configurar read e write concerns.
Por padrão, o Atlas distribui nós de cluster entre zonas de disponibilidade dentro de uma das regiões de disponibilidade do seu fornecedor de nuvem escolhido. Por exemplo, se o cluster estiver implantado na região do provedor de nuvem us-east
, o Atlas implantará nós no us-east-a
, us-east-b
e us-east-c
por padrão.
Para saber mais sobre alta disponibilidade e distribuição de nós entre regiões, consulte Orientação para Alta Disponibilidade do Atlas.
Implantações de autocura
Os Atlas clusters devem consistir em um número ímpar de nós, porque o pool de nós deve eleger um nó primário de e para o qual seu aplicação grava e lê diretamente. Um cluster que consiste em um número par de nós pode resultar em um bloqueio que impede que um nó primário seja eleito.
Caso um nó primário esteja indisponível, devido a interrupções de infraestrutura, períodos de manutenção ou qualquer outro motivo, os clusters Atlas se recuperam automaticamente promovendo um nó secundário à função de nó primário para manter a disponibilidade do banco de dados. Para aprender mais sobre esse processo, consulte Como o MongoDB Atlas oferece alta disponibilidade?
Tempo de atividade da janela de manutenção
O Atlas mantém a disponibilidade durante a manutenção programada aplicando atualizações de forma contínua a um nó por vez. Durante esse processo, o Atlas elege um novo primário quando necessário, assim como faz durante qualquer outra interrupção não planejada do nó primário.
Ao configurar um período de manutenção, selecione um horário que corresponda ao momento em que seu aplicativo tem o menor volume de tráfego.
Monitoramento
O Atlas oferece ferramentas integradas para monitorar o desempenho do cluster, o desempenho de queries e muito mais. Além disso, o Atlas se integra facilmente a serviços de terceiros.
Ao monitorar ativamente seus clusters, você pode obter insights valiosos sobre o desempenho de query e implantação. Para saber mais sobre monitoramento no Atlas, consulte Monitorar seus Clusters e Monitoramento e Alertas.
Teste de resiliência do sistema
Você pode simular diversos cenários que exigem fluxos de trabalho de recuperação de desastres para avaliar sua prontidão para tais eventos. Especificamente, com o Atlas você pode testar o failover do nó primário e simular interrupções regionais. Recomendamos fortemente que você execute esses testes antes de implantar um aplicativo para a produção.
Salvaguardas de encerramento de cluster
Você pode evitar a exclusão acidental de Atlas clusters ativando a proteção contra encerramento. Habilitar a proteção contra encerramento é especialmente importante ao aproveitar as ferramentas do IaC, como o Terraform, para garantir que uma reimplantação não provisione uma nova infraestrutura. Para excluir um cluster que tenha a proteção contra encerramento ativada, primeiro você deve desabilitar a proteção contra encerramento. Por padrão, o Atlas desativa a proteção contra encerramento para todos os clusters.
Backups de banco de dados
Os Backups do Atlas Cloud facilitam o armazenamento de backup na nuvem usando a funcionalidade nativa de snapshot do provedor de serviços de nuvem no qual seu cluster está implantado. Por exemplo, se você distribuir seu cluster na Amazon Web Services, poderá optar por fazer backup dos dados do cluster com instantâneos tirados em intervalos configuráveis no Amazon Web Services S.3
Para aprender mais sobre backup de banco de dados e recuperação de snapshot, consulte Fazer backup do seu cluster.
Para recomendações sobre backups, consulte Orientações para Backups do Atlas.
Recomendações para Resiliência do Atlas
Use o MongoDB 8.0 ou posterior
Para melhorar a resiliência do cluster, atualize-o para o MongoDB 8.0. O MongoDB 8.0 introduz as seguintes melhorias de desempenho e novas funcionalidades relacionadas à resiliência:
Filtros de exclusão de operações para mitigar de forma reativa queries dispendiosas
Tempo limite no nível do cluster para proteção proativa contra operações de leitura dispendiosas
Melhor isolamento do volume de trabalho com o comando moveCollection
Conectando seu Aplicativo ao Atlas
Recomendamos que você use um método de conexão criado na versão do driver mais atual para a linguagem de programação do seu aplicativo sempre que possível. E embora a string de conexão padrão fornecida Atlas seja um bom ponto de partida, você pode querer ajustá-la para desempenho no contexto de seu aplicação específico e arquitetura de implantação.
Por exemplo, talvez você queira definir um maxTimeMS
curto para um microsserviço que fornece um recurso de login, enquanto você pode querer definir o maxTimeMS
para um valor muito maior se o código do aplicação for uma solicitação de tarefa de análise de longa duração em relação a o cluster.
Ajustar as configurações do pool de conexões é particularmente importante no contexto de sistemas de aplicação de nível empresarial.
Considerações sobre pool de conexões para aplicativos de alto desempenho
A abertura de conexões de cliente de banco de dados é um dos processos que mais consomem recursos envolvidos na manutenção de um pool de conexões de cliente que facilita o acesso do aplicação ao seu Atlas cluster.
Por isso, vale a pena pensar em como e quando você gostaria que esse processo de abertura de conexões com cliente se desenrolasse no contexto do seu aplicação específico.
Por exemplo, se você estiver dimensionando seu Atlas cluster para atender à demanda dos usuários, considere qual o tamanho mínimo do pool de conexões que seu aplicação precisará consistentemente, para que, quando o pool de aplicação for dimensionado, a rede adicional e a carga de computação que vem com a abertura de novas conexões de cliente não 't minar a necessidade sensível do tempo do seu aplicativo de mais operações de banco de dados .
Tamanho mínimo e máximo do pool de conexões
Se os valores minPoolSize
e maxPoolSize
forem semelhantes, a maioria das conexões de cliente do banco de dados será aberta na inicialização do aplicação . Por exemplo, se o minPoolSize
estiver definido como 10
e o maxPoolSize
estiver definido como 12
, 10 conexões de cliente serão abertas na inicialização do aplicação e somente mais 2 conexões poderão ser abertas durante o tempo de execução do aplicação . No entanto, se o seu minPoolSize
estiver configurado para 10
e o seu maxPoolSize
estiver configurado para 100
, até 90 conexões adicionais poderão ser abertas conforme necessário durante o tempo de execução do aplicação .
Sobrecarga de rede adicional associada à abertura de novas conexões de cliente . Portanto, considere se você prefere incorrer nesse custo de rede na inicialização do aplicação ou incorrer dinamicamente conforme a necessidade durante o tempo de execução do aplicação , que tem o potencial de impacto a latência operacional e o desempenho percebido para os usuários finais se houver um pico súbita nas solicitações que exige que um grande número de conexões adicionais sejam abertas de uma só vez.
A arquitetura do aplicativo é fundamental para essa consideração. Se, por exemplo, você distribuir seu aplicação como microsserviços, considere quais serviços devem chamar o Atlas diretamente como um meio de controlar a expansão e contração dinâmicas do seu pool de conexões. Como alternativa, se o sistema do aplicação estiver aproveitando recursos de thread único, como o Amazon Web Services Lambda, seu aplicação só poderá abrir e usar uma conexão de cliente , portanto, seu minPoolSize
e seu maxPoolSize
devem ser definidos como 1
.
Tempo limite da consulta
Quase invariavelmente, as queries específicas da carga de trabalho do seu aplicativo variam em termos do tempo que levam para serem executadas no Atlas e em do tempo que seu aplicativo pode esperar por uma resposta.
Você pode definir o comportamento do tempo limite da query globalmente no Atlas ou diretamente na query.
Leituras e gravações de banco de dados repetíveis
O Atlas oferece suporte a operações de leitura e gravações repetíveis . Quando ativado, o Atlas tenta novamente as operações de leitura e gravação uma vez como proteção contra interrupções intermitentes da rede.
Configurar write and read concerns
Os clusters Atlas, em algum momento, replicam todos os dados em todos os nós. No entanto, é possível configurar o número de nós nos quais os dados devem ser replicados antes que uma operação de leitura ou gravação seja considerada bem-sucedida. Você pode definir a preocupação de leitura e a preocupação de gravação globalmente no Atlas ou na conta do cliente pela sua string de conexão. O Atlas tem uma preocupação de gravação padrão de majority
, o que significa que os dados devem ser replicados em mais da metade dos nós do seu cluster antes que o Atlas dispare um aviso de sucesso. Por outro lado, o Atlas possui uma preocupação de leitura padrão de local
, o que significa que, ao ser consultado, o Atlas recupera dados de apenas um nó no seu cluster.
Isolar o impacto de collections ativas e não fragmentadas
A fragmentação permite que você escale seu cluster horizontalmente. Com o MongoDB, você pode fragmentar algumas collections e, ao mesmo tempo, permitir que outras collections no mesmo cluster permaneçam não fragmentadas. Quando você cria um novo banco de dados de dados, o fragmento no cluster com a menor quantidade de dados é escolhido como o fragmento primário desse banco de dados por padrão. Todas as collections não fragmentadas desse banco de dados de dados residem nesse fragmento primário por padrão. Isso pode causar um aumento no tráfego para o fragmento primário à medida que sua carga de trabalho cresce, especialmente se o crescimento do volume de trabalho se concentrar nas coleções não fragmentadas do fragmento primário.
Para distribuir melhor esse volume de trabalho, o MongoDB 8.0 permite mover uma coleção não fragmentada do fragmento primário para outros shards com o comando moveCollection
. Isso permite que você coloque collections ativas e sobrecarregadas em shards com um uso menor de recursos. Com isso, você pode:
Otimize o desempenho em volumes de trabalho maiores e complexos.
Obtenha uma melhor utilização dos recursos.
Distribua a data de forma mais uniforme entre os fragmentos.
Recomendamos isolar sua coleção nas seguintes circunstâncias:
Se o seu fragmento primário tiver uma carga de trabalho significativa devido à presença de várias collections não fragmentadas de alta taxa de transferência.
Você antecipa uma coleção não fragmentada para experimentar um crescimento futuro, o que pode se tornar um gargalo para outras coleções.
Você está executando um design de implantação de uma collection por cluster e deseja isolar esses clientes com base em prioridade ou volumes de trabalho.
Seus shards têm uma quantidade mais do que proporcional de dados devido ao número de collections não fragmentadas localizadas neles.
Para saber como mover uma collection não fragmentada com mongosh
, consulte Mover uma collection.
Recuperação de desastres
Para recomendações sobre as melhores práticas de recuperação de desastres para o Atlas, consulte Orientações para Recuperação de desastres do Atlas e Configurações recomendadas para Alta Disponibilidade e Recuperação.
Aplicação de exemplo resiliente
O aplicativo de exemplo reúne as seguintes recomendações para garantir a resiliência contra interrupções de rede e eventos de failover:
Use a cadeia de conexão fornecida pelo Atlas com gravações repetíveis, preocupação de gravação majoritária e preocupação de leitura padrão.
Especifique um limite de optime com o método maxTimeMS . Para obter instruções sobre como configurar o
maxTimeMS
, consulte sua Documentação do Driverespecífica.Lidar com erros de chaves duplicadas e tempos-limite.
O aplicativo é uma API HTTP que permite aos clientes criar ou listar registros de usuário. Ele expõe um ponto de extremidade que aceita solicitações GET e POST http://localhost:3000:
Método | Endpoint | Descrição |
---|---|---|
|
| Obtém uma lista de nomes de usuário de uma coleção do |
|
| Exige um |
Observação
1 // File: App.java 2 3 import java.util.Map; 4 import java.util.logging.Logger; 5 6 import org.bson.Document; 7 import org.json.JSONArray; 8 9 import com.mongodb.MongoException; 10 import com.mongodb.client.MongoClient; 11 import com.mongodb.client.MongoClients; 12 import com.mongodb.client.MongoCollection; 13 import com.mongodb.client.MongoDatabase; 14 15 import fi.iki.elonen.NanoHTTPD; 16 17 public class App extends NanoHTTPD { 18 private static final Logger LOGGER = Logger.getLogger(App.class.getName()); 19 20 static int port = 3000; 21 static MongoClient client = null; 22 23 public App() throws Exception { 24 super(port); 25 26 // Replace the uri string with your MongoDB deployment's connection string 27 String uri = "<atlas-connection-string>"; 28 client = MongoClients.create(uri); 29 30 start(NanoHTTPD.SOCKET_READ_TIMEOUT, false); 31 LOGGER.info("\nStarted the server: http://localhost:" + port + "/ \n"); 32 } 33 34 public static void main(String[] args) { 35 try { 36 new App(); 37 } catch (Exception e) { 38 LOGGER.severe("Couldn't start server:\n" + e); 39 } 40 } 41 42 43 public Response serve(IHTTPSession session) { 44 StringBuilder msg = new StringBuilder(); 45 Map<String, String> params = session.getParms(); 46 47 Method reqMethod = session.getMethod(); 48 String uri = session.getUri(); 49 50 if (Method.GET == reqMethod) { 51 if (uri.equals("/")) { 52 msg.append("Welcome to my API!"); 53 } else if (uri.equals("/users")) { 54 msg.append(listUsers(client)); 55 } else { 56 msg.append("Unrecognized URI: ").append(uri); 57 } 58 } else if (Method.POST == reqMethod) { 59 try { 60 String name = params.get("name"); 61 if (name == null) { 62 throw new Exception("Unable to process POST request: 'name' parameter required"); 63 } else { 64 insertUser(client, name); 65 msg.append("User successfully added!"); 66 } 67 } catch (Exception e) { 68 msg.append(e); 69 } 70 } 71 72 return newFixedLengthResponse(msg.toString()); 73 } 74 75 static String listUsers(MongoClient client) { 76 MongoDatabase database = client.getDatabase("test"); 77 MongoCollection<Document> collection = database.getCollection("users"); 78 79 final JSONArray jsonResults = new JSONArray(); 80 collection.find().forEach((result) -> jsonResults.put(result.toJson())); 81 82 return jsonResults.toString(); 83 } 84 85 static String insertUser(MongoClient client, String name) throws MongoException { 86 MongoDatabase database = client.getDatabase("test"); 87 MongoCollection<Document> collection = database.getCollection("users"); 88 89 collection.insertOne(new Document().append("name", name)); 90 return "Successfully inserted user: " + name; 91 } 92 }
Observação
O aplicativo de servidor a seguir usa o Express, que você precisa adicionar ao seu projeto como uma dependência antes de executá-lo.
1 const express = require('express'); 2 const bodyParser = require('body-parser'); 3 4 // Use the latest drivers by installing & importing them 5 const MongoClient = require('mongodb').MongoClient; 6 7 const app = express(); 8 app.use(bodyParser.json()); 9 app.use(bodyParser.urlencoded({ extended: true })); 10 11 const uri = "mongodb+srv://<db_username>:<db_password>@cluster0-111xx.mongodb.net/test?retryWrites=true&w=majority"; 12 13 const client = new MongoClient(uri, { 14 useNewUrlParser: true, 15 useUnifiedTopology: true 16 }); 17 18 // ----- API routes ----- // 19 app.get('/', (req, res) => res.send('Welcome to my API!')); 20 21 app.get('/users', (req, res) => { 22 const collection = client.db("test").collection("users"); 23 24 collection 25 .find({}) 26 .maxTimeMS(5000) 27 .toArray((err, data) => { 28 if (err) { 29 res.send("The request has timed out. Please check your connection and try again."); 30 } 31 return res.json(data); 32 }); 33 }); 34 35 app.post('/users', (req, res) => { 36 const collection = client.db("test").collection("users"); 37 collection.insertOne({ name: req.body.name }) 38 .then(result => { 39 res.send("User successfully added!"); 40 }, err => { 41 res.send("An application error has occurred. Please try again."); 42 }) 43 }); 44 // ----- End of API routes ----- // 45 46 app.listen(3000, () => { 47 console.log(`Listening on port 3000.`); 48 client.connect(err => { 49 if (err) { 50 console.log("Not connected: ", err); 51 process.exit(0); 52 } 53 console.log('Connected.'); 54 }); 55 });
Observação
O seguinte aplicação da web usa FastAPI. Para criar um novo aplicação, use o arquivo de amostra FastAPI estrutura.
1 # File: main.py 2 3 from fastapi import FastAPI, Body, Request, Response, HTTPException, status 4 from fastapi.encoders import jsonable_encoder 5 6 from typing import List 7 from models import User 8 9 import pymongo 10 from pymongo import MongoClient 11 from pymongo import errors 12 13 # Replace the uri string with your |service| connection string 14 uri = "<atlas-connection-string>" 15 db = "test" 16 17 app = FastAPI() 18 19 20 def startup_db_client(): 21 app.mongodb_client = MongoClient(uri) 22 app.database = app.mongodb_client[db] 23 24 25 def shutdown_db_client(): 26 app.mongodb_client.close() 27 28 ##### API ROUTES ##### 29 30 def list_users(request: Request): 31 try: 32 users = list(request.app.database["users"].find().max_time_ms(5000)) 33 return users 34 except pymongo.errors.ExecutionTimeout: 35 raise HTTPException(status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail="The request has timed out. Please check your connection and try again.") 36 37 38 def new_user(request: Request, user: User = Body(...)): 39 user = jsonable_encoder(user) 40 try: 41 new_user = request.app.database["users"].insert_one(user) 42 return {"message":"User successfully added!"} 43 except pymongo.errors.DuplicateKeyError: 44 raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Could not create user due to existing '_id' value in the collection. Try again with a different '_id' value.")