Estratégias de active-active e active-passive em clusters de banco de dados

1. Fundamentos dos Modelos de Cluster em Banco de Dados

1.1. Definição e objetivos de clusters de banco de dados

Clusters de banco de dados são conjuntos de servidores interconectados que trabalham de forma coordenada para oferecer alta disponibilidade, escalabilidade e tolerância a falhas. O objetivo principal é garantir que o sistema permaneça operacional mesmo diante de falhas de hardware, rede ou software, minimizando o tempo de inatividade e a perda de dados.

1.2. Diferenças conceituais entre Active-Active e Active-Passive

No modelo Active-Passive, apenas um nó (primário) processa requisições de leitura e escrita, enquanto os nós secundários (passivos) mantêm cópias atualizadas dos dados e assumem o controle apenas em caso de falha. Já no modelo Active-Active, todos os nós aceitam operações de leitura e escrita simultaneamente, distribuindo a carga e aumentando a capacidade de processamento.

1.3. Cenários de uso típicos

Sistemas transacionais (OLTP) geralmente adotam Active-Passive para garantir consistência forte e baixa latência de escrita. Sistemas analíticos (OLAP) e aplicações geodistribuídas preferem Active-Active para maximizar a disponibilidade e reduzir a latência de leitura em regiões distintas.

2. Arquitetura Active-Passive (Primário-Secundário)

2.1. Funcionamento

O nó primário é o único que aceita operações de escrita. Os nós passivos sincronizam os dados através de replicação e permanecem prontos para assumir como primário em caso de falha. Esse modelo é simples de implementar e oferece consistência forte.

2.2. Mecanismos de replicação

A replicação pode ser síncrona (o primário aguarda confirmação do secundário antes de confirmar a transação) ou assíncrona (o primário confirma a transação imediatamente e replica os dados posteriormente). A replicação síncrona garante zero perda de dados, mas aumenta a latência.

2.3. Processo de failover

Quando o nó primário falha, um sistema de monitoramento detecta a falha e inicia a eleição de um novo primário entre os nós passivos. O nó promovido assume as operações de escrita e os clientes são redirecionados automaticamente.

Exemplo de configuração de failover com PostgreSQL e Patroni:

# Configuração do Patroni para cluster PostgreSQL
scope: mycluster
namespace: /service/
name: node1

restapi:
  listen: 0.0.0.0:8008
  connect_address: 192.168.1.10:8008

etcd:
  host: 192.168.1.100:2379

bootstrap:
  dcs:
    ttl: 30
    loop_wait: 10
    retry_timeout: 10
    maximum_lag_on_failover: 1048576
    postgresql:
      use_pg_rewind: true
      parameters:
        max_connections: 100

postgresql:
  listen: 0.0.0.0:5432
  connect_address: 192.168.1.10:5432
  data_dir: /var/lib/postgresql/data
  pgpass: /tmp/pgpass
  authentication:
    replication:
      username: replicator
      password: secret
    superuser:
      username: postgres
      password: secret

3. Arquitetura Active-Active (Multimestre)

3.1. Funcionamento

Todos os nós do cluster aceitam operações de leitura e escrita simultaneamente. As alterações são propagadas entre os nós através de replicação multimestre, permitindo que o sistema continue operando mesmo se um nó falhar.

3.2. Desafios de consistência

O principal desafio é resolver conflitos de escrita quando dois nós modificam o mesmo registro simultaneamente. Estratégias comuns incluem:
- Última escrita vence (LWW): baseada em timestamp
- Merge manual: conflitos são registrados para resolução posterior
- CRDTs (Conflict-free Replicated Data Types): estruturas de dados que resolvem conflitos automaticamente

3.3. Estratégias de roteamento de tráfego

O balanceamento de carga distribui as requisições entre os nós ativos. A afinidade de sessão (sticky sessions) garante que um mesmo cliente seja direcionado ao mesmo nó durante uma sessão, reduzindo conflitos.

Exemplo de configuração de cluster Cassandra (Active-Active):

# Configuração do cassandra.yaml para cluster multimestre
cluster_name: 'MyCluster'
num_tokens: 256
seed_provider:
  - class_name: org.apache.cassandra.locator.SimpleSeedProvider
    parameters:
      - seeds: "192.168.1.10,192.168.1.11,192.168.1.12"

listen_address: 192.168.1.10
rpc_address: 0.0.0.0
endpoint_snitch: GossipingPropertyFileSnitch

# Estratégia de replicação para keyspace
# CREATE KEYSPACE mykeyspace WITH replication = {'class': 'NetworkTopologyStrategy', 'datacenter1': 3};

4. Replicação e Sincronização de Dados

4.1. Replicação síncrona vs. assíncrona

A replicação síncrona oferece consistência forte, mas aumenta a latência e reduz a disponibilidade em cenários de partição de rede. A replicação assíncrona prioriza disponibilidade e desempenho, mas pode resultar em perda de dados em falhas.

4.2. Modelos de replicação

  • Log-based: replica o log de transações (WAL) — usado pelo PostgreSQL
  • Trigger-based: utiliza triggers para capturar alterações — usado pelo MySQL
  • Statement-based: replica comandos SQL executados — obsoleto em versões modernas

4.3. Gerenciamento de conflitos em Active-Active

A detecção de conflitos ocorre durante a replicação. A resolução automática pode usar timestamps, vetores de versão ou algoritmos de consenso (Raft, Paxos). A resolução manual envolve registrar conflitos em tabelas específicas para análise posterior.

5. Failover, Recuperação e RTO/RPO

5.1. Estratégias de failover

No Active-Passive, o failover automático é acionado por health checks periódicos. No Active-Active, o failover é transparente, pois os nós restantes continuam operando normalmente.

5.2. Métricas de continuidade

  • RTO (Recovery Time Objective): tempo máximo para recuperação após falha
  • RPO (Recovery Point Objective): quantidade máxima de dados perdidos

Para sistemas críticos, RTO < 1 minuto e RPO = 0 (replicação síncrona) são desejáveis.

5.3. Técnicas de recuperação

Após uma falha, o nó recuperado deve ser re-sincronizado com o nó primário (Active-Passive) ou com os demais nós (Active-Active). Técnicas como pg_rewind no PostgreSQL ou nodetool repair no Cassandra garantem a consistência.

6. Casos de Uso e Exemplos Práticos

6.1. Active-Passive: PostgreSQL com Patroni

Sistemas bancários e ERPs utilizam Active-Passive para garantir consistência forte e failover rápido. O Patroni gerencia automaticamente a eleição do primário e a reconfiguração dos clientes.

6.2. Active-Active: Cassandra e CockroachDB

Aplicações globais como redes sociais e IoT utilizam Active-Active para oferecer baixa latência em múltiplas regiões. O Cassandra utiliza consistência eventual e resolução de conflitos LWW, enquanto o CockroachDB implementa consistência forte com algoritmos de consenso.

6.3. Comparação de desempenho

Característica Active-Passive Active-Active
Throughput de escrita Limitado ao nó primário Escalável horizontalmente
Latência de escrita Baixa (consistência forte) Variável (depende da resolução de conflitos)
Escalabilidade Vertical Horizontal
Complexidade Baixa Alta

7. Considerações Finais e Melhores Práticas

7.1. Critérios de escolha

Escolha Active-Passive quando a consistência forte for crítica e o volume de escritas for moderado. Opte por Active-Active quando a disponibilidade global e a escalabilidade horizontal forem prioridades, mesmo com possíveis conflitos de dados.

7.2. Monitoramento e observabilidade

Implemente health checks em todos os nós, monitore o lag de replicação e configure alertas para falhas de sincronização. Ferramentas como Prometheus e Grafana são essenciais para visualizar métricas de desempenho e disponibilidade.

7.3. Tendências futuras

Clusters híbridos que combinam Active-Passive para dados críticos e Active-Active para dados menos sensíveis estão se tornando comuns. A orquestração com Kubernetes e operadores especializados (PostgreSQL Operator, Cassandra Operator) simplifica o gerenciamento e a escalabilidade.

Referências