Arquitectura Interna
Diseño de Particiones
Cada topic del pipeline CDC está configurado con 3 particiones y 3 réplicas:
apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaTopic
metadata:
name: cdc.public.customers
namespace: kafka-cdc
labels:
strimzi.io/cluster: cdc-cluster
spec:
partitions: 3
replicas: 3
config:
retention.ms: 604800000
cleanup.policy: compact
¿Por qué 3 particiones?
| Factor | Decisión |
|---|---|
Paralelismo |
3 particiones permiten hasta 3 consumidores simultáneos en un consumer group |
Replicación |
Con RF=3 y |
Orden |
Debezium usa la primary key como partition key, garantizando orden por registro |
Escalabilidad |
Se puede aumentar particiones sin downtime (solo se agregan, nunca se eliminan) |
Partition Key en CDC
Debezium usa el primary key del registro como partition key. Esto garantiza que todos los cambios de un mismo registro van a la misma partición, preservando el orden:
Registro con id=1 → Partition 0 Registro con id=2 → Partition 1 Registro con id=3 → Partition 2 Registro con id=4 → Partition 0 (hash wraps)
Consumer Groups y Escalabilidad
El pipeline tiene dos consumer groups principales:
| Consumer Group | Componente | Réplicas |
|---|---|---|
|
KafkaConnect (Debezium + HTTP Sink) |
2 |
|
Apache Camel CDC Processor |
2 |
Balanceo de particiones
Con 3 particiones y 2 consumidores:
Consumer 0: Partition 0, Partition 1 Consumer 1: Partition 2
Si un consumidor cae, Kafka rebalancea automáticamente:
Consumer 1: Partition 0, Partition 1, Partition 2
Al escalar a 3 réplicas, cada consumidor procesa exactamente 1 partición (distribución óptima).
Manejo de Offsets y Checkpoints
Offsets de Kafka
Cada consumer group mantiene su posición (offset) por partición en el topic interno __consumer_offsets:
oc exec -it cdc-cluster-kafka-0 -n kafka-cdc -- bin/kafka-consumer-groups.sh \
--bootstrap-server localhost:9092 \
--describe --group camel-cdc-consumer
Checkpoints de Debezium
Debezium mantiene su propio checkpoint via el replication slot de PostgreSQL y los offset topics de KafkaConnect:
config:
offset.storage.topic: cdc-connect-offsets
config.storage.topic: cdc-connect-configs
status.storage.topic: cdc-connect-status
offset.storage.replication.factor: 3
config.storage.replication.factor: 3
status.storage.replication.factor: 3
-
cdc-connect-offsets— posición actual en el WAL de PostgreSQL -
cdc-connect-configs— configuración de los connectors -
cdc-connect-status— estado de las tasks
Los 3 topics tienen replication.factor: 3 para sobrevivir la pérdida de un broker.
Replication Slot de PostgreSQL
Debezium crea un replication slot para no perder cambios si el connector se reinicia:
config:
slot.name: debezium_cdc
publication.name: cdc_publication
snapshot.mode: initial
-
slot.name— nombre del slot lógico en PostgreSQL -
snapshot.mode: initial— al iniciar por primera vez, Debezium captura un snapshot completo de las tablas
Para verificar el slot:
oc exec -it deploy/cdc-postgresql -n kafka-cdc -- psql -U cdcuser -d cdcdb -c \
"SELECT slot_name, plugin, slot_type, active FROM pg_replication_slots;"
Retención y Reprocesamiento
Políticas de retención
| Topic | Retención | Cleanup Policy |
|---|---|---|
|
7 días (604800000 ms) |
|
|
7 días (604800000 ms) |
|
|
30 días (2592000000 ms) |
|
|
30 días (2592000000 ms) |
|
¿Qué es cleanup.policy: compact?
Con compact, Kafka retiene solo el último valor para cada key, eliminando versiones anteriores. Para CDC:
-
Se preserva el estado actual de cada registro
-
Se eliminan updates intermedios después de la compactación
-
Permite reconstruir el estado completo de una tabla consumiendo el topic desde el inicio
Reprocesamiento
Para reprocesar eventos, se puede resetear el offset del consumer group:
oc exec -it cdc-cluster-kafka-0 -n kafka-cdc -- bin/kafka-consumer-groups.sh \
--bootstrap-server localhost:9092 \
--group camel-cdc-consumer \
--topic cdc.public.customers \
--reset-offsets --to-earliest \
--execute
| Esto causa que todos los mensajes del topic se reprocesen. Usar con precaución en producción. |
Configuración de Replicación
El cluster Kafka tiene los siguientes parámetros de replicación para garantizar durabilidad:
config:
offsets.topic.replication.factor: 3
transaction.state.log.replication.factor: 3
transaction.state.log.min.isr: 2
default.replication.factor: 3
min.insync.replicas: 2
-
min.insync.replicas: 2— un write es confirmado solo si 2 de las 3 réplicas lo persisten -
default.replication.factor: 3— todos los topics nuevos se crean con RF=3
Esto significa que el cluster puede tolerar la pérdida de 1 broker sin perder datos ni disponibilidad.
How it Works
Escritura en Kafka: de producer a disco
Cuando Debezium (o cualquier producer) envía un mensaje a Kafka, internamente ocurre:
-
El producer serializa el key y value, calcula
hash(key) % numPartitionspara determinar la partición destino. -
El producer agrupa mensajes en batches por partición (configurable via
batch.sizeylinger.ms) para optimizar I/O. -
El batch se envía al broker leader de la partición via TCP.
-
El leader escribe el batch en un segment file en disco — un append-only log. Los segments se rotan al llegar a 1GB (configurable).
-
Cada mensaje recibe un offset secuencial: un entero de 64 bits, monotónicamente creciente, único dentro de la partición.
-
Los followers fetch el batch del leader, lo escriben en sus propios segments, y envían un ACK al leader.
-
Con
acks=all(default en Strimzi) ymin.insync.replicas=2, el leader solo confirma al producer cuando al menos 2 réplicas persisten el dato.
Lectura en Kafka: consumer groups
-
Cada consumer del grupo se conecta al group coordinator (un broker elegido para gestionar el grupo).
-
El coordinator ejecuta un partition assignment protocol (range o round-robin) distribuyendo las particiones entre los consumers.
-
Cada consumer hace
poll()periódicamente al leader de sus particiones asignadas, recibiendo batches de mensajes desde su último offset. -
El consumer procesa los mensajes y luego commitea el offset al topic interno
__consumer_offsets. -
Si un consumer se desconecta (no envía heartbeat en
session.timeout.ms), el coordinator dispara un rebalance: las particiones huérfanas se reasignan a los consumers restantes.
Compactación: cleanup.policy=compact
Para topics CDC con cleanup.policy: compact:
-
Kafka ejecuta periódicamente un log cleaner que escanea los segments cerrados.
-
Para cada key, retiene solo el mensaje con el mayor offset (el más reciente).
-
Los mensajes con key duplicada y offset menor se eliminan físicamente del disco.
-
Un mensaje con value
null(tombstone) marca el key para eliminación completa después del periododelete.retention.ms. -
Resultado: el topic contiene exactamente un mensaje por key — el estado actual de cada registro de la base de datos.
Network Policies
El namespace kafka-cdc está protegido con NetworkPolicy que restringe el tráfico de ingress:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: kafka-cdc-allow-internal
namespace: kafka-cdc
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kafka-cdc
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: openshift-cluster-observability-operator
ports:
- protocol: TCP
port: 9404
-
Solo pods dentro de
kafka-cdcpueden comunicarse entre sí -
El namespace de observabilidad puede acceder al puerto de métricas (9404) para scraping de Prometheus
Pod Disruption Budgets
Los PDBs garantizan que las operaciones de mantenimiento (drains, upgrades) no dejen el pipeline sin capacidad:
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: kafka-brokers-pdb
namespace: kafka-cdc
spec:
minAvailable: 2
selector:
matchLabels:
strimzi.io/cluster: cdc-cluster
strimzi.io/kind: Kafka
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: kafka-connect-pdb
namespace: kafka-cdc
spec:
minAvailable: 1
selector:
matchLabels:
strimzi.io/cluster: cdc-connect
strimzi.io/kind: KafkaConnect
-
kafka-brokers-pdb— siempre hay al menos 2 brokers de los 3 disponibles -
kafka-connect-pdb— siempre hay al menos 1 worker de Connect de los 2 disponibles
Documentación Oficial
-
Apache Kafka Design — Arquitectura interna de Kafka (particiones, replicación, almacenamiento)
-
Configuring Kafka Topics — Gestión de topics con Strimzi
-
Strimzi Configuration Guide — Configuración avanzada de operadores y CRs
-
Kafka Consumer Configurations — Parámetros de consumer groups y offsets
-
Pod Scheduling and Disruption Budgets — PDBs y scheduling en OpenShift