Introdução ao CockroachDB: PostgreSQL distribuído sem ops complexo

1. Por que CockroachDB? O problema da escalabilidade em bancos relacionais

Bancos relacionais tradicionais como o PostgreSQL monólito enfrentam limitações severas quando o volume de dados e a taxa de requisições crescem além da capacidade de uma única máquina. O administrador precisa recorrer a soluções complexas: sharding manual (particionamento lógico da base em múltiplos servidores), replicação assíncrona com risco de perda de dados, ou soluções de clustering que exigem conhecimento profundo de infraestrutura.

O CockroachDB surge como uma alternativa "NewSQL" e "cloud-native". Ele oferece a semântica familiar de um banco SQL relacional (compatível com PostgreSQL) enquanto gerencia automaticamente a distribuição dos dados entre centenas de nós, replicação síncrona e tolerância a falhas. Diferente de soluções como sharding manual, onde você precisa decidir como particionar os dados e lidar com falhas de nós manualmente, o CockroachDB faz isso de forma transparente.

2. Arquitetura fundamental: como o CockroachDB distribui dados

O CockroachDB organiza todos os dados em ranges — pedaços contíguos de dados ordenados por chave primária. Cada range tem um tamanho alvo (normalmente 64 MB) e é automaticamente dividido (split) ou mesclado (merge) conforme necessário.

A replicação é feita de forma síncrona usando o protocolo de consenso Raft. Cada range é replicado em 3 ou mais nós (configurável). Para cada range, um nó é eleito líder e coordena todas as operações de escrita. As operações de leitura podem ser servidas por qualquer réplica, dependendo da configuração de consistência.

Transações distribuídas utilizam Serializable Snapshot Isolation (SSI), garantindo que o banco se comporte como se cada transação fosse executada em série, mesmo quando envolvem múltiplos ranges e nós.

3. Compatibilidade com PostgreSQL: o que funciona e o que muda

O CockroachDB implementa o protocolo wire do PostgreSQL, o que significa que você pode usar drivers PostgreSQL padrão (psycopg2, pq, libpq) sem alterações no código da aplicação. A sintaxe SQL é amplamente compatível:

CREATE TABLE usuarios (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    nome STRING NOT NULL,
    email STRING UNIQUE,
    criado_em TIMESTAMP DEFAULT now()
);

INSERT INTO usuarios (nome, email) VALUES ('Maria Silva', 'maria@exemplo.com');

SELECT * FROM usuarios WHERE email = 'maria@exemplo.com';

No entanto, existem diferenças importantes:

  • Triggers e stored procedures: Não são suportados (embora stored procedures estejam em desenvolvimento)
  • Sequências: Suporte parcial, recomenda-se usar UUIDs ou sequences distribuídas
  • Índices parciais e expressões: Suportados de forma similar ao PostgreSQL
  • Full-text search: Não implementado nativamente

Para migração, ferramentas como pg_dump e pg_restore funcionam, mas é necessário ajustar tipos de dados incompatíveis (ex: SERIAL vira INT DEFAULT unique_rowid()).

4. Operações sem complexidade: deploy e gerenciamento simplificados

O CockroachDB foi projetado para operar com mínima intervenção manual:

  • Rebalanceamento automático: Quando um nó é adicionado ou removido, o sistema redistribui os ranges automaticamente
  • Failover: Se um nó falha, as réplicas dos ranges que estavam nele são eleitas em outros nós sem perda de dados
  • Upgrades rolling: É possível atualizar a versão do banco nó por nó sem downtime, graças à compatibilidade entre versões consecutivas
  • Backup e restore: Comandos SQL nativos para backup full e incremental para armazenamento externo (S3, GCS, Azure)
-- Backup do banco inteiro
BACKUP DATABASE minha_app INTO 's3://meu-bucket/backups' AS OF SYSTEM TIME '-10s';

-- Restore
RESTORE DATABASE minha_app FROM 's3://meu-bucket/backups';

5. Casos de uso ideais e limitações

Casos ideais:

  • Aplicações multi-região: O CockroachDB permite configurar zonas de replicação para manter dados próximos dos usuários, com latência de leitura abaixo de 10ms mesmo em cenários globais
  • Sistemas críticos: Onde alta disponibilidade (99.999%) e consistência forte são requisitos não negociáveis (fintech, saúde, e-commerce)
  • SaaS multi-tenant: O particionamento automático permite isolar dados de clientes sem overhead operacional

Limitações:

  • Workloads OLTP com alta contenção: Transações concorrentes que acessam as mesmas linhas podem sofrer abortos devido ao SSI
  • Custo de rede: Operações que envolvem múltiplos ranges e nós têm latência adicional devido ao consenso Raft
  • Performance de joins complexos: Em cenários com muitos dados distribuídos, joins podem ser mais lentos que em bancos tradicionais otimizados para consultas analíticas

6. Primeiros passos práticos: rodando um cluster local

Para iniciar um cluster de 3 nós localmente (certifique-se de ter o CockroachDB instalado):

# Terminal 1 - Nó 1
cockroach start --insecure --store=node1 --listen-addr=localhost:26257 --http-addr=localhost:8080 --join=localhost:26257,localhost:26258,localhost:26259 --background

# Terminal 2 - Nó 2
cockroach start --insecure --store=node2 --listen-addr=localhost:26258 --http-addr=localhost:8081 --join=localhost:26257,localhost:26258,localhost:26259 --background

# Terminal 3 - Nó 3
cockroach start --insecure --store=node3 --listen-addr=localhost:26259 --http-addr=localhost:8082 --join=localhost:26257,localhost:26258,localhost:26259 --background

# Inicializar o cluster
cockroach init --insecure --host=localhost:26257

Agora, conecte-se ao SQL:

cockroach sql --insecure --host=localhost:26257

Crie uma tabela e veja a replicação em ação:

CREATE DATABASE loja;
USE loja;

CREATE TABLE produtos (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    nome STRING NOT NULL,
    preco DECIMAL(10,2),
    estoque INT DEFAULT 0
);

INSERT INTO produtos (nome, preco, estoque) VALUES ('Teclado Mecânico', 299.90, 50);
INSERT INTO produtos (nome, preco, estoque) VALUES ('Mouse Gamer', 149.90, 100);

-- Verifique como os dados estão distribuídos
SHOW RANGES FROM TABLE produtos;

Para ver o dashboard de monitoramento, acesse http://localhost:8080 no navegador.

Comandos úteis para gerenciamento:

-- Listar nós do cluster
cockroach node ls --insecure --host=localhost:26257

-- Verificar status de replicação
cockroach node status --insecure --host=localhost:26257

-- Configurar zona de replicação (ex: manter 3 réplicas)
ALTER TABLE produtos CONFIGURE ZONE USING num_replicas = 3;

7. Monitoramento e ajustes para produção

O dashboard embutido (porta HTTP 8080) oferece métricas essenciais:

  • Latência de queries: P95 e P99 por nó
  • Throughput: Operações de leitura/escrita por segundo
  • Replicação: Estado das réplicas, ranges sub-replicados ou não saudáveis
  • Hardware: CPU, memória, disco e rede por nó

Ajustes comuns para produção:

-- Configurar zonas de replicação para dados críticos
ALTER DATABASE dados_sensiveis CONFIGURE ZONE USING num_replicas = 5;

-- Priorizar leituras locais em uma região específica
ALTER TABLE pedidos CONFIGURE ZONE USING constraints = '{"+region=us-east": 1}';

-- Configurar garbage collection para versões antigas de dados
ALTER TABLE historico CONFIGURE ZONE USING gc.ttlseconds = 86400; -- 24 horas

Para dimensionamento, considere que cada nó deve ter pelo menos 4 CPUs e 8 GB de RAM para workloads moderados. O custo de rede entre regiões deve ser monitorado, pois cada operação de escrita em múltiplas regiões envolve latência de confirmação via Raft.

Referências