Debezium: captura de mudanças de banco de dados para pipelines de eventos

1. Introdução ao Debezium e ao CDC (Change Data Capture)

Em arquiteturas modernas orientadas a eventos, capturar cada alteração em bancos de dados relacionais em tempo real tornou-se um requisito fundamental. O Change Data Capture (CDC) é a técnica que permite observar e registrar mudanças em bancos de dados — inserts, updates e deletes — e transformá-las em eventos que alimentam pipelines de dados.

O Debezium é uma plataforma open-source construída sobre o Apache Kafka Connect que implementa CDC de forma robusta e escalável. Em vez de depender de polling periódico ou triggers no banco, o Debezium lê diretamente os logs de transação do banco de dados (como o binlog do MySQL ou o WAL do PostgreSQL), capturando cada mudança com baixa latência.

Os casos de uso são amplos: sincronização entre bancos de dados, comunicação entre microsserviços, auditoria de dados, alimentação de data lakes, atualização de caches e muito mais. O Debezium transforma bancos de dados em fontes de eventos, permitindo que sistemas downstream reajam instantaneamente a qualquer alteração.

2. Arquitetura e Componentes do Debezium

O Debezium opera como um conjunto de conectores source para o Kafka Connect. Cada conector é especializado em um banco de dados específico:

  • MySQL: lê o binlog e suporta formatos ROW, STATEMENT e MIXED
  • PostgreSQL: utiliza o mecanismo de replicação lógica (WAL)
  • MongoDB: monitora a oplog do replica set
  • Oracle: usa LogMiner ou XStream
  • SQL Server: baseia-se no CDC nativo ou no log de transações

A arquitetura típica envolve:

[Banco de Dados] → [Conector Debezium] → [Kafka Connect] → [Tópico Kafka] → [Consumidores]

Quando o conector é iniciado, ele primeiro realiza um snapshot inicial — uma cópia completa do estado atual das tabelas configuradas. Após o snapshot, a captura muda para o modo incremental, onde apenas as mudanças nos logs de transação são processadas. Isso garante consistência e eficiência.

3. Configuração e Implantação do Debezium

Para implantar o Debezium, é necessário ter um cluster Apache Kafka em execução e o Kafka Connect configurado (modo standalone ou distribuído). Abaixo, um exemplo de configuração para conectar a um banco MySQL.

Primeiro, certifique-se de que o banco MySQL tenha o binlog ativado com formato ROW:

[mysqld]
server-id=1
log-bin=mysql-bin
binlog-format=ROW
binlog-row-image=FULL

Em seguida, registre o conector via API REST do Kafka Connect:

curl -i -X POST -H "Accept:application/json" -H "Content-Type:application/json" \
  http://localhost:8083/connectors/ \
  -d '{
    "name": "mysql-connector",
    "config": {
      "connector.class": "io.debezium.connector.mysql.MySqlConnector",
      "database.hostname": "192.168.1.100",
      "database.port": "3306",
      "database.user": "debezium",
      "database.password": "dbz_pass",
      "database.server.id": "1",
      "database.server.name": "dbserver1",
      "database.include.list": "inventory",
      "table.include.list": "inventory.customers,inventory.orders",
      "database.history.kafka.bootstrap.servers": "kafka:9092",
      "database.history.kafka.topic": "schema-changes.inventory",
      "include.schema.changes": "true"
    }
  }'

Parâmetros críticos:

  • database.server.name: define o prefixo dos tópicos Kafka criados
  • table.include.list: filtra quais tabelas monitorar
  • database.history.kafka.topic: armazena o histórico de esquemas do banco

Após o registro, o conector inicia automaticamente o snapshot e começa a publicar eventos no tópico dbserver1.inventory.customers.

4. Fluxo de Eventos e Estrutura de Mensagens

Cada mudança capturada pelo Debezium é serializada em uma mensagem Kafka. O formato padrão é JSON, mas é possível usar Avro com o Schema Registry. A estrutura de um evento contém:

  • op: tipo de operação (c = create, u = update, d = delete, r = snapshot read)
  • before: estado anterior do registro (null para inserts)
  • after: estado atual do registro (null para deletes)
  • source: metadados da origem (banco, tabela, posição no log, timestamp)
  • ts_ms: timestamp do evento no Debezium

Exemplo de evento para um INSERT:

{
  "schema": { ... },
  "payload": {
    "op": "c",
    "before": null,
    "after": {
      "id": 1001,
      "first_name": "Ana",
      "last_name": "Silva",
      "email": "ana@exemplo.com"
    },
    "source": {
      "version": "2.5.0.Final",
      "connector": "mysql",
      "name": "dbserver1",
      "ts_ms": 1712345678000,
      "snapshot": "false",
      "db": "inventory",
      "table": "customers",
      "server_id": 1,
      "file": "mysql-bin.000003",
      "pos": 154
    },
    "ts_ms": 1712345678123
  }
}

Para um UPDATE:

{
  "op": "u",
  "before": { "id": 1001, "first_name": "Ana", "email": "ana@exemplo.com" },
  "after":  { "id": 1001, "first_name": "Ana", "email": "ana.nova@exemplo.com" },
  "source": { ... },
  "ts_ms": 1712345680000
}

Para um DELETE:

{
  "op": "d",
  "before": { "id": 1001, "first_name": "Ana", "email": "ana.nova@exemplo.com" },
  "after": null,
  "source": { ... },
  "ts_ms": 1712345685000
}

5. Tratamento de Casos Complexos e Boas Práticas

Evolução de esquemas: quando colunas são adicionadas ou removidas no banco, o Debezium pode detectar a mudança via database.history.kafka.topic. Para evitar quebra em consumidores, utilize Schema Registry com Avro e configure políticas de compatibilidade (BACKWARD, FORWARD, FULL).

Gerenciamento de offsets: o Kafka Connect armazena offsets (posição no log de transação) em um tópico interno. Se o conector falhar, ele retoma do último offset registrado. Para reiniciar um snapshot, é necessário resetar o offset manualmente.

Filtragem com SMTs: Single Message Transforms permitem modificar eventos antes de serem enviados. Exemplo para remover o campo before em eventos de INSERT:

"transforms": "unwrap",
"transforms.unwrap.type": "io.debezium.transforms.ExtractNewRecordState",
"transforms.unwrap.drop.tombstones": "false"

6. Integração com Pipelines de Eventos e Ferramentas

Os eventos publicados pelo Debezium podem ser consumidos por qualquer aplicação ou framework que se conecte ao Kafka. Exemplos comuns:

Pipeline para Elasticsearch: um conector sink Kafka Connect Elasticsearch pode indexar documentos em tempo real:

curl -X POST http://localhost:8083/connectors/ \
  -d '{
    "name": "elastic-sink",
    "config": {
      "connector.class": "io.confluent.connect.elasticsearch.ElasticsearchSinkConnector",
      "topics": "dbserver1.inventory.customers",
      "connection.url": "http://elasticsearch:9200",
      "type.name": "_doc",
      "key.ignore": "true",
      "schema.ignore": "true"
    }
  }'

Processamento com Kafka Streams: é possível juntar streams de diferentes tabelas, detectar padrões ou enriquecer eventos:

KStream<String, Customer> customers = builder.stream("dbserver1.inventory.customers");
KStream<String, Order> orders = builder.stream("dbserver1.inventory.orders");

customers.join(orders,
    (customer, order) -> new EnrichedOrder(customer, order),
    JoinWindows.of(Duration.ofMinutes(5)),
    StreamJoined.with(Serdes.String(), customerSerde, orderSerde));

Monitoramento: métricas como kafka.consumer:type=connector-metrics no JMX permitem acompanhar lag, taxa de eventos e erros. Ferramentas como Prometheus + Grafana ou Confluent Control Center ajudam na observabilidade.

7. Limitações, Alternativas e Cenários de Uso

Limitações:

  • Dependência de Apache Kafka: toda a infraestrutura deve suportar Kafka
  • Latência adicional: embora baixa, existe overhead na leitura dos logs de transação
  • Consumo de recursos no banco de origem: especialmente em bancos com alto volume de writes
  • Complexidade operacional: gerenciar conectores, offsets e schema evolution exige conhecimento

Alternativas:

  • AWS Database Migration Service (DMS): CDC gerenciado para ambientes AWS, sem necessidade de Kafka
  • Oracle GoldenGate: solução enterprise para Oracle e outros bancos, com alta performance
  • Maxwell's Daemon: alternativa leve para MySQL, escreve diretamente no Kafka como produtor JSON

Quando escolher Debezium:

  • Você já utiliza Apache Kafka como backbone de eventos
  • Precisa de suporte a múltiplos bancos de dados (MySQL, PostgreSQL, MongoDB, etc.)
  • Deseja uma solução open-source com comunidade ativa e extensa documentação
  • Requer captura de mudanças com consistência transacional e baixa latência

Para cenários simples ou ambientes totalmente gerenciados, alternativas como AWS DMS podem ser mais adequadas. Porém, para pipelines de eventos flexíveis, escaláveis e que exigem controle fino, o Debezium é a escolha dominante.

Referências