📚 Estudo: CouchDB – Replicação e Cluster
1. Subindo duas instâncias isoladas para testes
Arquivo docker-compose.yml simples com duas instâncias separadas:
version: "3.9"
 
services:
  couchdb1:
    image: couchdb:3
    container_name: couchdb1
    environment:
      - COUCHDB_USER=admin
      - COUCHDB_PASSWORD=admin
    ports:
      - "5984:5984"
    networks:
      - couchdbnet
 
  couchdb2:
    image: couchdb:3
    container_name: couchdb2
    environment:
      - COUCHDB_USER=admin
      - COUCHDB_PASSWORD=admin
    ports:
      - "5985:5984"
    networks:
      - couchdbnet
 
networks:
  couchdbnet:
    driver: bridgeAcesso via API / Fauxton
- Instância 1: http://localhost:5984/_utils/
- Instância 2: http://localhost:5985/_utils/Login:admin/admin.
2. Replicação entre duas instâncias
2.1 Replicação pontual (one-shot)
# Criar base na origem
curl -X PUT http://admin:admin@localhost:5984/minha_base
 
# Inserir documento exemplo
curl -X POST http://admin:admin@localhost:5984/minha_base \
  -H "Content-Type: application/json" \
  -d '{"_id":"doc1","tipo":"exemplo","ok":true}'
 
# Replicar origem -> destino
curl -X POST http://admin:admin@localhost:5984/_replicate \
  -H "Content-Type: application/json" \
  -d '{
    "source": "http://admin:admin@localhost:5984/minha_base",
    "target": "http://admin:admin@localhost:5985/minha_base",
    "create_target": true
  }'2.2 Replicação contínua (_replicator)
# Criar DB de replicações (se não existir)
curl -X PUT http://admin:admin@localhost:5984/_replicator
 
# Criar replicação contínua
curl -X POST http://admin:admin@localhost:5984/_replicator \
  -H "Content-Type: application/json" \
  -d '{
    "_id": "replica-minha_base-para-5985",
    "source": "http://admin:admin@localhost:5984/minha_base",
    "target": "http://admin:admin@localhost:5985/minha_base",
    "create_target": true,
    "continuous": true,
    "user_ctx": { "name": "admin", "roles": ["_admin"] }
  }'2.3 Replicação com filtro
Criar filtro:
curl -X PUT http://admin:admin@localhost:5984/minha_base/_design/rep \
  -H "Content-Type: application/json" \
  -d '{
    "filters": {
      "somente_tipo_exemplo": "function(doc, req) { return doc.tipo === \"exemplo\"; }"
    }
  }'Usar filtro na replicação:
curl -X POST http://admin:admin@localhost:5984/_replicate \
  -H "Content-Type: application/json" \
  -d '{
    "source": "http://admin:admin@localhost:5984/minha_base",
    "target": "http://admin:admin@localhost:5985/minha_base",
    "create_target": true,
    "filter": "rep/somente_tipo_exemplo"
  }'3. Configurando um Cluster
3.1 docker-compose.yml para cluster
version: "3.9"
 
services:
  couchdb1:
    image: couchdb:3
    container_name: couchdb1
    hostname: couchdb1
    environment:
      - NODENAME=couchdb@couchdb1
      - COUCHDB_USER=admin
      - COUCHDB_PASSWORD=admin
      - COUCHDB_SECRET=super-secret-long-random-string
      - ERL_FLAGS=-setcookie couchdb-cluster-cookie
    ports:
      - "5984:5984"
    volumes:
      - c1data:/opt/couchdb/data
    networks:
      - couchdbnet
 
  couchdb2:
    image: couchdb:3
    container_name: couchdb2
    hostname: couchdb2
    environment:
      - NODENAME=couchdb@couchdb2
      - COUCHDB_USER=admin
      - COUCHDB_PASSWORD=admin
      - COUCHDB_SECRET=super-secret-long-random-string
      - ERL_FLAGS=-setcookie couchdb-cluster-cookie
    ports:
      - "5985:5984"
    volumes:
      - c2data:/opt/couchdb/data
    networks:
      - couchdbnet
 
networks:
  couchdbnet:
    driver: bridge
 
volumes:
  c1data:
  c2data:Importante:
- NODENAMEdiferente por nó, mas mesmo- COUCHDB_SECRETe cookie (- -setcookie).
- Ambos na mesma rede couchdbnet.
3.2 Configuração via API
USER=admin
PASS=admin
 
# Checar nós
curl -s http://$USER:$PASS@localhost:5984/ | jq .
curl -s http://$USER:$PASS@localhost:5985/ | jq .
 
# 1) Habilitar cluster no nó 1
curl -s -X POST http://$USER:$PASS@localhost:5984/_cluster_setup \
  -H "Content-Type: application/json" \
  -d '{
    "action":"enable_cluster",
    "bind_address":"0.0.0.0",
    "username":"'"$USER"'",
    "password":"'"$PASS"'",
    "port":5984,
    "node_count":"2",
    "remote_node":"couchdb2",
    "remote_current_user":"'"$USER"'",
    "remote_current_password":"'"$PASS"'"
  }' | jq .
 
# 2) Adicionar nó 2
curl -s -X POST http://$USER:$PASS@localhost:5984/_cluster_setup \
  -H "Content-Type: application/json" \
  -d '{
    "action":"add_node",
    "host":"couchdb2",
    "port":5984,
    "username":"'"$USER"'",
    "password":"'"$PASS"'"
  }' | jq .
 
# 3) Finalizar cluster
curl -s -X POST http://$USER:$PASS@localhost:5984/_cluster_setup \
  -H "Content-Type: application/json" \
  -d '{"action":"finish_cluster"}' | jq .
 
# 4) Verificar membros
curl -s http://$USER:$PASS@localhost:5984/_membership | jq .3.3 Criando base no cluster
# 8 shards, 2 réplicas
curl -s -X PUT "http://$USER:$PASS@localhost:5984/minha_base" \
  -H "Content-Type: application/json" \
  -d '{"q":8,"n":2}' | jq .
 
# Ver shards
curl -s "http://$USER:$PASS@localhost:5984/minha_base/_shards" | jq .4. Vantagens do Cluster
- Alta disponibilidade: tolerância a falhas com réplicas automáticas.
- Escalabilidade horizontal: sharding e distribuição de carga.
- Gerenciamento unificado: acesso a todos os nós via um único endpoint.
- Resiliência de dados: fator de réplica garante recuperação em caso de perda.
- Balanceamento automático: coordenação de leitura/escrita entre nós.
- Menos risco de inconsistência: replicação interna e controlada por quorum.
Com isso, você tem:
- Cenário de duas instâncias isoladas para testar replicação manual.
- Cenário de cluster real com sharding, replicação automática e quorum.
- Exemplos práticos de docker-compose, chamadascurle explicações.
