Apache Zookeeper: O coordenador de sistemas distribuídos

Apache Zookeeper é um serviço centralizado para manter informações de configuração, nomenclatura, sincronização distribuída e serviços de grupo em sistemas distribuídos. Desenvolvido originalmente pelo Yahoo!, tornou-se um projeto Apache de alto nível …


This content originally appeared on DEV Community and was authored by Thiago da Silva Adriano

Apache Zookeeper é um serviço centralizado para manter informações de configuração, nomenclatura, sincronização distribuída e serviços de grupo em sistemas distribuídos. Desenvolvido originalmente pelo Yahoo!, tornou-se um projeto Apache de alto nível e é amplamente usado em ecossistemas de big data.

Características principais

  • Coordenação distribuída: sincronização entre múltiplos nós
  • Consistência forte: garantias ACID para operações críticas
  • Alta disponibilidade: tolerância a falhas com replicação
  • Performance: baixa latência para operações de leitura
  • Simplicidade: API simples baseada em sistema de arquivos

O problema que o Zookeeper resolve

Desafios de sistemas distribuídos

Problema da eleição de líder:

Cenário: 3 brokers Kafka precisam eleger um líder para uma partição
Sem Zookeeper: Como garantir que apenas um seja eleito?
Com Zookeeper: Algoritmo de consenso garante eleição única e consistente

Problema da configuração distribuída:

Cenário: 10 serviços precisam da mesma configuração atualizada
Sem Zookeeper: Cada serviço mantém sua própria cópia (inconsistência)
Com Zookeeper: Configuração centralizada com notificações automáticas

Problema da descoberta de serviços:

Cenário: Microserviços precisam encontrar uns aos outros
Sem Zookeeper: IPs hardcoded ou DNS complexo
Com Zookeeper: Registro dinâmico com health checks

Antes do Zookeeper: soluções inadequadas

Arquivos de configuração estáticos:

# broker1.properties
broker.id=1
listeners=PLAINTEXT://192.168.1.10:9092

# broker2.properties  
broker.id=2
listeners=PLAINTEXT://192.168.1.11:9092

Problemas:

  • Configuração manual: alterações exigem restart de serviços
  • Inconsistência: diferentes versões de configuração
  • Falta de coordenação: sem sincronização entre nós
  • Detecção de falhas: sem mecanismo automático

Bancos de dados relacionais:

CREATE TABLE cluster_config (
    key VARCHAR(255),
    value TEXT,
    updated_at TIMESTAMP
);

Problemas:

  • Single point of failure: banco centralizado
  • Latência: queries SQL para cada operação
  • Complexidade: transações distribuídas complexas
  • Escalabilidade: limitada pela capacidade do banco

Como o Zookeeper funciona

Modelo de dados hierárquico

O Zookeeper organiza dados em uma estrutura de árvore similar a um sistema de arquivos:

/
├── kafka/
│   ├── brokers/
│   │   ├── ids/
│   │   │   ├── 1 → {"host":"kafka1","port":9092}
│   │   │   ├── 2 → {"host":"kafka2","port":9092}
│   │   │   └── 3 → {"host":"kafka3","port":9092}
│   │   └── topics/
│   │       └── ecommerce.produtos/
│   │           └── partitions/
│   │               ├── 0 → {"leader":1,"replicas":[1,2]}
│   │               └── 1 → {"leader":2,"replicas":[2,3]}
│   ├── controller/
│   │   └── epoch → {"brokerid":1,"epoch":15}
│   └── config/
│       └── topics/
│           └── ecommerce.produtos → {"retention.ms":604800000}
└── debezium/
    └── connectors/
        └── ecommerce-connector/
            ├── status → "RUNNING"
            └── config → {"database.hostname":"sqlserver"}

Tipos de nós (znodes)

Nós persistentes:

  • Permanecem até serem explicitamente deletados
  • Usados para configurações e metadados
  • Exemplo: /kafka/config/topics/meu-topico

Nós efêmeros:

  • Deletados automaticamente quando a sessão termina
  • Usados para detecção de falhas e presença
  • Exemplo: /kafka/brokers/ids/1 (broker ativo)

Nós sequenciais:

  • Recebem sufixo numérico automático
  • Usados para eleição de líder e filas
  • Exemplo: /kafka/controller/election/n_0000000001

Algoritmo de consenso

Zookeeper usa uma variação do algoritmo Zab (Zookeeper Atomic Broadcast):

  1. Fase de eleição: nós elegem um líder
  2. Fase de descoberta: líder coleta estado dos seguidores
  3. Fase de sincronização: líder sincroniza todos os nós
  4. Fase de broadcast: líder processa escritas e replica
Líder (Zookeeper 1)     Seguidor (Zookeeper 2)    Seguidor (Zookeeper 3)
       |                        |                         |
   1. Proposta ----------------> |                         |
       |                   2. ACK                         |
       |                        |                         |
   3. Proposta ---------------------------------> |
       |                        |            4. ACK
   5. Commit -----------------> |                         |
   6. Commit ---------------------------------> |

Papel do Zookeeper no ecossistema Kafka

Gerenciamento de brokers

Registro de brokers:

// /kafka/brokers/ids/1
{
  "version": 4,
  "host": "kafka-broker-1",
  "port": 9092,
  "jmx_port": 9999,
  "timestamp": "1640995200000",
  "endpoints": ["PLAINTEXT://kafka-broker-1:9092"],
  "rack": "rack1"
}

Detecção de falhas:

  • Brokers mantêm sessões efêmeras com Zookeeper
  • Se broker falha, nó efêmero é removido automaticamente
  • Outros brokers são notificados da mudança

Eleição de controller

O Kafka Controller é o broker responsável por:

  • Gerenciar partições e réplicas
  • Coordenar eleições de líder de partição
  • Processar mudanças de metadados

Processo de eleição:

1. Broker 1 tenta criar /kafka/controller (nó efêmero)
2. Se sucesso → Broker 1 vira controller
3. Se falha → outro broker já é controller
4. Todos os brokers assistem /kafka/controller para mudanças

Metadados de tópicos e partições

Configuração de tópico:

// /kafka/config/topics/ecommerce-produtos
{
  "version": 1,
  "config": {
    "retention.ms": "604800000",
    "cleanup.policy": "delete",
    "compression.type": "snappy"
  }
}

Estado de partições:

// /kafka/brokers/topics/ecommerce-produtos
{
  "version": 1,
  "partitions": {
    "0": [1, 2, 3],  // broker 1 é líder, 2 e 3 são réplicas
    "1": [2, 3, 1],  // broker 2 é líder, 3 e 1 são réplicas
    "2": [3, 1, 2]   // broker 3 é líder, 1 e 2 são réplicas
  }
}

Arquitetura e componentes

Ensemble Zookeeper

Um ensemble é um cluster de servidores Zookeeper que trabalham juntos:

Cliente 1 ──┐
Cliente 2 ──┼─── Zookeeper 1 (Líder)
Cliente 3 ──┘         │
                       │ Replicação
                       ├─── Zookeeper 2 (Seguidor)
                       │
                       └─── Zookeeper 3 (Seguidor)

Características do ensemble:

  • Número ímpar: 3, 5, 7 nós (evita split-brain)
  • Quorum: maioria deve estar ativa (2/3, 3/5, 4/7)
  • Líder único: processa todas as escritas
  • Seguidores: processam leituras e replicam escritas

Sessões e watches

Sessões:

  • Conexão entre cliente e ensemble
  • Timeout configurável (heartbeat)
  • Estado mantido enquanto sessão ativa

Watches (observadores):

// Cliente Java registra watch
zk.exists("/kafka/brokers/ids/1", new Watcher() {
    public void process(WatchedEvent event) {
        if (event.getType() == Event.EventType.NodeDeleted) {
            System.out.println("Broker 1 falhou!");
        }
    }
});

Tipos de eventos:

  • NodeCreated: nó foi criado
  • NodeDeleted: nó foi removido
  • NodeDataChanged: dados do nó mudaram
  • NodeChildrenChanged: filhos do nó mudaram

Configuração e deployment

Configuração básica

zoo.cfg:

# Identificação do servidor
tickTime=2000
initLimit=10
syncLimit=5

# Diretório de dados
dataDir=/var/lib/zookeeper

# Porta para clientes
clientPort=2181

# Configuração do ensemble
server.1=zk1:2888:3888
server.2=zk2:2888:3888  
server.3=zk3:2888:3888

# Configurações de performance
maxClientCnxns=60
autopurge.snapRetainCount=3
autopurge.purgeInterval=1

Explicação dos parâmetros:

  • tickTime: unidade básica de tempo (ms)
  • initLimit: tempo para seguidores se conectarem ao líder
  • syncLimit: tempo para seguidores sincronizarem
  • 2888: porta para comunicação entre servidores
  • 3888: porta para eleição de líder

Configuração para produção

Otimizações de performance:

# Aumentar heap JVM
export JVMFLAGS="-Xmx4G -Xms4G"

# Configurações de rede
maxClientCnxns=0
minSessionTimeout=4000
maxSessionTimeout=40000

# Configurações de disco
preAllocSize=65536
snapCount=100000

# Configurações de log
zookeeper.log.threshold=INFO

Monitoramento:

# Habilitar métricas JMX
com.sun.management.jmxremote=true
com.sun.management.jmxremote.port=9999
com.sun.management.jmxremote.authenticate=false
com.sun.management.jmxremote.ssl=false

Operações e comandos essenciais

Cliente de linha de comando

Conectar ao Zookeeper:

# Conectar ao ensemble
zkCli.sh -server zk1:2181,zk2:2181,zk3:2181

Comandos básicos:

# Listar nós filhos
ls /kafka/brokers/ids

# Obter dados de um nó
get /kafka/controller

# Criar nó
create /teste "dados do teste"

# Atualizar nó
set /teste "novos dados"

# Deletar nó
delete /teste

# Estatísticas do nó
stat /kafka/brokers/ids/1

Comandos administrativos

Status do ensemble:

# Verificar status de cada servidor
echo stat | nc zk1 2181
echo stat | nc zk2 2181  
echo stat | nc zk3 2181

# Verificar líder
echo srvr | nc zk1 2181 | grep Mode

Limpeza de dados:

# Limpar snapshots antigos
zkCleanup.sh -n 3

# Verificar integridade
zkServer.sh status

Monitoramento e observabilidade

Métricas importantes

Métricas de performance:

  • zk_avg_latency: latência média de operações
  • zk_max_latency: latência máxima
  • zk_packets_received: pacotes recebidos por segundo
  • zk_packets_sent: pacotes enviados por segundo

Métricas de saúde:

  • zk_followers: número de seguidores conectados
  • zk_pending_syncs: sincronizações pendentes
  • zk_open_file_descriptor_count: descritores de arquivo abertos
  • zk_max_file_descriptor_count: limite de descritores

Ferramentas de monitoramento

JMX com Prometheus:

# prometheus.yml
- job_name: 'zookeeper'
  static_configs:
    - targets: ['zk1:9999', 'zk2:9999', 'zk3:9999']

Comandos de diagnóstico:

# Verificar conexões ativas
echo cons | nc localhost 2181

# Verificar watches ativos  
echo wchs | nc localhost 2181

# Verificar estatísticas detalhadas
echo mntr | nc localhost 2181

Troubleshooting comum

Problemas de conectividade

Sintoma: Clientes não conseguem conectar

# Verificar se porta está aberta
telnet zk1 2181

# Verificar logs
tail -f /var/log/zookeeper/zookeeper.log

# Verificar configuração de rede
netstat -tlnp | grep 2181

Solução:

  • Verificar firewall e regras de rede
  • Confirmar configuração de clientPort
  • Validar DNS/resolução de nomes

Split-brain e quorum

Sintoma: Ensemble não consegue formar quorum

2024-01-15 10:30:00 WARN [QuorumPeer] Not enough followers present, giving up

Diagnóstico:

# Verificar status de cada nó
for server in zk1 zk2 zk3; do
    echo "=== $server ==="
    echo stat | nc $server 2181 | grep Mode
done

Solução:

  • Garantir que maioria dos nós esteja ativa
  • Verificar conectividade entre servidores
  • Reiniciar nós em sequência se necessário

Performance degradada

Sintoma: Alta latência em operações

# Verificar métricas de latência
echo mntr | nc localhost 2181 | grep latency

Otimizações:

  • Aumentar heap JVM se necessário
  • Configurar preAllocSize adequado
  • Mover dataDir para SSD
  • Ajustar snapCount conforme carga

Evolução: Kafka sem Zookeeper (KRaft)

Limitações do Zookeeper

Complexidade operacional:

  • Componente adicional para gerenciar
  • Configuração e monitoramento separados
  • Ponto de falha adicional

Limitações de escalabilidade:

  • Metadados limitados pela capacidade do Zookeeper
  • Latência adicional para operações administrativas
  • Complexidade de backup e recovery

KRaft (Kafka Raft)

A partir do Kafka 2.8, foi introduzido o KRaft mode:

Kafka com Zookeeper:
Kafka Brokers ←→ Zookeeper Ensemble

Kafka com KRaft:
Kafka Controllers + Kafka Brokers (self-managed)

Vantagens do KRaft:

  • Simplicidade: menos componentes para gerenciar
  • Performance: menor latência para metadados
  • Escalabilidade: suporte a milhões de partições
  • Consistência: modelo de dados unificado

Status atual:

  • Kafka 3.3+: KRaft production-ready
  • Migração gradual do Zookeeper para KRaft
  • Zookeeper ainda amplamente usado em produção

Casos de uso além do Kafka

Descoberta de serviços

Registro dinâmico:

// Serviço se registra no Zookeeper
String servicePath = "/services/user-service/" + instanceId;
zk.create(servicePath, serviceInfo.getBytes(), 
          ZooDefs.Ids.OPEN_ACL_UNSAFE, 
          CreateMode.EPHEMERAL);

Descoberta por clientes:

// Cliente descobre serviços disponíveis
List<String> instances = zk.getChildren("/services/user-service", true);

Configuração distribuída

Configuração centralizada:

// Atualizar configuração
zk.setData("/config/app-settings", newConfig.getBytes(), -1);

// Clientes recebem notificação automática via watch
zk.getData("/config/app-settings", new ConfigWatcher(), null);

Coordenação de tarefas

Lock distribuído:

// Implementação de mutex distribuído
String lockPath = "/locks/resource-x/" + Thread.currentThread().getId();
zk.create(lockPath, new byte[0], 
          ZooDefs.Ids.OPEN_ACL_UNSAFE, 
          CreateMode.EPHEMERAL_SEQUENTIAL);

Boas práticas

Configuração de produção

Ensemble sizing:

  • 3 nós: desenvolvimento e testes
  • 5 nós: produção com alta disponibilidade
  • 7+ nós: apenas para casos muito críticos

Hardware:

  • CPU: 4+ cores para ensemble de produção
  • RAM: 8GB+ com heap JVM de 4GB
  • Disco: SSD para dataDir e dataLogDir
  • Rede: baixa latência entre nós do ensemble

Segurança

Autenticação:

# SASL/Kerberos
authProvider.1=org.apache.zookeeper.server.auth.SASLAuthenticationProvider
requireClientAuthScheme=sasl

Autorização:

// ACLs para controle de acesso
zk.create("/secure/path", data, 
          Arrays.asList(new ACL(ZooDefs.Perms.ALL, new Id("digest", "user:password"))),
          CreateMode.PERSISTENT);

Backup e recovery

Backup de dados:

# Backup do dataDir
tar -czf zk-backup-$(date +%Y%m%d).tar.gz /var/lib/zookeeper

# Backup via snapshot
zkServer.sh snapshot /var/lib/zookeeper/version-2

Recovery:

# Restaurar dados
service zookeeper stop
rm -rf /var/lib/zookeeper/version-2/*
tar -xzf zk-backup-20240115.tar.gz -C /
service zookeeper start

Conclusão

Apache Zookeeper é o alicerce que permite a operação confiável de sistemas distribuídos como Apache Kafka. Sua capacidade de fornecer coordenação, consistência e detecção de falhas de forma transparente torna possível construir arquiteturas complexas e resilientes.


This content originally appeared on DEV Community and was authored by Thiago da Silva Adriano


Print Share Comment Cite Upload Translate Updates
APA

Thiago da Silva Adriano | Sciencx (2025-09-28T14:36:48+00:00) Apache Zookeeper: O coordenador de sistemas distribuídos. Retrieved from https://www.scien.cx/2025/09/28/apache-zookeeper-o-coordenador-de-sistemas-distribuidos/

MLA
" » Apache Zookeeper: O coordenador de sistemas distribuídos." Thiago da Silva Adriano | Sciencx - Sunday September 28, 2025, https://www.scien.cx/2025/09/28/apache-zookeeper-o-coordenador-de-sistemas-distribuidos/
HARVARD
Thiago da Silva Adriano | Sciencx Sunday September 28, 2025 » Apache Zookeeper: O coordenador de sistemas distribuídos., viewed ,<https://www.scien.cx/2025/09/28/apache-zookeeper-o-coordenador-de-sistemas-distribuidos/>
VANCOUVER
Thiago da Silva Adriano | Sciencx - » Apache Zookeeper: O coordenador de sistemas distribuídos. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2025/09/28/apache-zookeeper-o-coordenador-de-sistemas-distribuidos/
CHICAGO
" » Apache Zookeeper: O coordenador de sistemas distribuídos." Thiago da Silva Adriano | Sciencx - Accessed . https://www.scien.cx/2025/09/28/apache-zookeeper-o-coordenador-de-sistemas-distribuidos/
IEEE
" » Apache Zookeeper: O coordenador de sistemas distribuídos." Thiago da Silva Adriano | Sciencx [Online]. Available: https://www.scien.cx/2025/09/28/apache-zookeeper-o-coordenador-de-sistemas-distribuidos/. [Accessed: ]
rf:citation
» Apache Zookeeper: O coordenador de sistemas distribuídos | Thiago da Silva Adriano | Sciencx | https://www.scien.cx/2025/09/28/apache-zookeeper-o-coordenador-de-sistemas-distribuidos/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.