Saltar al contenido

Etiqueta: CDC

Cómo levantar una demo CDC con SQL Server, Debezium y Kafka (Part 2): guía paso a paso

En la primera parte expliqué la arquitectura de la demo y las decisiones de diseño detrás de SQL Server, Debezium, Kafka Connect, Kafka UI y el visor web. En esta segunda parte me concentro en la ejecución: cómo levantar el entorno, validar que CDC esté funcionando y probar el flujo completo con cambios reales.

Prerrequisitos

Antes de arrancar, necesitas Docker Desktop o Docker Engine con Docker Compose v2, puertos libres para SQL Server, Kafka Connect, Kafka UI, Kafka y Web Viewer, y memoria suficiente para que SQL Server no estrangule el resto del stack. Si estás en Windows, la demo trae scripts tanto en PowerShell como en bash.

  • Docker Compose v2 operativo
  • Puertos 1433, 8083, 8080, 9092 y 3000 disponibles o remapeados
  • Al menos unos 4 GB libres, porque SQL Server es el servicio más pesado
  • Acceso a bash o PowerShell según tu flujo

Paso 1: levantar la infraestructura

El arranque base se hace con docker compose up -d. Eso levanta SQL Server, Kafka en KRaft, Kafka Connect, Kafka UI y el Web Viewer. El orden importa, y por eso el stack usa healthchecks y dependencias condicionales para que Connect no intente arrancar antes de que Kafka y SQL Server estén listos.

Secuencia de arranque del stack CDC con Docker Compose
Secuencia de arranque y dependencias entre servicios.

Una vez arriba, lo primero que vale la pena comprobar es el estado de los contenedores. Todos deberían aparecer como running y, cuando aplique, como healthy.

docker compose ps

Paso 2: inicializar SQL Server y habilitar CDC

La imagen oficial de SQL Server no ejecuta automáticamente scripts de inicialización como sí hacen otras bases en algunos escenarios, así que la demo incluye scripts dedicados para aplicar la base DemoCDC, crear dbo.Clientes, habilitar CDC e insertar datos semilla.

./scripts/apply-sql.sh
# o en PowerShell
./scripts/apply-sql.ps1

Ese paso hace cuatro cosas importantes:

  1. Crea la base de datos DemoCDC.
  2. Crea la tabla dbo.Clientes con clave primaria.
  3. Habilita CDC a nivel de base y de tabla.
  4. Inserta tres registros semilla para que el snapshot inicial tenga contenido visible.

Si quieres verificar que CDC quedó realmente activo, puedes consultar sys.databases o usar sp_cdc_help_change_data_capture dentro del contenedor.

Paso 3: registrar el connector Debezium

Con la base preparada, el siguiente paso es registrar el connector en Kafka Connect. La configuración vive en un JSON comentado, lo que facilita entender cada parámetro clave: host y puerto de SQL Server, base capturada, tabla incluida, topic prefix, modo de snapshot y topic interno de historial de esquema.

./connect/register-connector.sh
# o en PowerShell
./connect/register-connector.ps1

En cuanto se registra, Debezium ejecuta el snapshot inicial. Ese snapshot emite un evento por cada fila ya existente, usando op = "r". Después de eso, el connector entra en modo streaming para capturar INSERT, UPDATE y DELETE nuevos.

Paso 4: validar el snapshot inicial

La demo permite observar los mismos eventos por tres caminos: Kafka UI, consola y Web Viewer. Para una explicación técnica, Kafka UI es muy útil; para una presentación o demo en vivo, el Web Viewer suele ser el más efectivo porque hace visible el patrón sin pedirle al espectador que lea JSON desde el minuto uno.

  • Kafka UI: ideal para ver topics, mensajes y estado del connector.
  • Consola: útil para validar rápidamente el stream en texto plano.
  • Web Viewer: pensado para mostrar el snapshot y los cambios como tarjetas y contadores en tiempo real.

Si todo salió bien, deberías ver tres eventos del snapshot inicial, uno por cada cliente semilla.

Paso 5: probar INSERT, UPDATE y DELETE

Una vez validado el snapshot, toca probar cambios reales. La demo incluye tres scripts listos para disparar un INSERT, un UPDATE y un DELETE. Lo ideal es ejecutarlos uno a uno y observar cómo aparecen en el topic y en el visor web.

./scripts/apply-sql.sh 03-test-insert.sql
./scripts/apply-sql.sh 04-test-update.sql
./scripts/apply-sql.sh 05-test-delete.sql

Cada uno se refleja como una operación distinta:

  • INSERT: op = "c"
  • UPDATE: op = "u" con before y after
  • DELETE: op = "d", seguido de un tombstone para compaction

Anatomía de un evento Debezium

Uno de los puntos más didácticos de Debezium es que no solo te dice que algo cambió, sino qué cambió y de dónde vino. Un evento típico de UPDATE trae el estado previo, el nuevo estado, el tipo de operación y metadatos como base, esquema, tabla y posición en el log.

{
  "payload": {
    "before": { "Id": 1, "Estado": "ACTIVO" },
    "after":  { "Id": 1, "Estado": "INACTIVO" },
    "op": "u",
    "ts_ms": 1751277900000,
    "source": {
      "connector": "sqlserver",
      "db": "DemoCDC",
      "schema": "dbo",
      "table": "Clientes"
    }
  }
}

Ese formato hace que luego sea mucho más fácil alimentar consumidores técnicos, dashboards, ETL o sistemas de auditoría.

Troubleshooting más común

Hay cuatro fallos que concentran la mayoría de los problemas en esta clase de demo:

  • Login failed for user sa: la contraseña del connector no coincide con la del entorno.
  • CDC no habilitado: la inicialización SQL no se ejecutó o se hizo antes de que SQL Server Agent estuviera listo.
  • Connector en FAILED: suele verse enseguida en el endpoint de status de Kafka Connect.
  • Web Viewer desconectado: el topic no existe todavía o el consumidor arrancó antes del registro del connector.

Por eso vale la pena apoyarse en docker compose logs y en el endpoint de estado del connector desde el principio.

Qué cambiaría para llevar esta demo a producción

Una demo local tiene que optimizar por claridad, no por dureza operativa. En producción yo cambiaría al menos estas piezas:

  • Más de un broker Kafka y replicación mayor a 1.
  • TLS, autenticación y ACLs en Kafka.
  • Schema Registry y serialización Avro o Protobuf.
  • Un usuario mínimo en SQL Server en lugar de usar sa.
  • Métricas y alertas con Prometheus y Grafana.
  • Al menos un sink connector para materializar eventos en otro destino.

Esas mejoras no invalidan la demo; al contrario, la convierten en una buena base pedagógica desde la que puedes evolucionar el patrón sin tener que rediseñarlo por completo.

Conclusión

Si tu objetivo es entender CDC de forma práctica, esta demo cubre el recorrido esencial: habilitas captura en SQL Server, registras Debezium, validas el snapshot y observas cómo cada cambio se convierte en un evento consumible. Ese es el valor real del patrón.

Si aún no viste el contexto completo de arquitectura, vuelve a la primera parte, donde explico por qué esta demo está diseñada así y qué trade-offs asume.

La demo de todo lo anteriormente explicado, pueden revisarla en el siguiente video.

YouTube player

Finalmente, les comparto el repositorio:

REPO GITHUB

Deja un comentario

CDC con SQL Server, Kafka y Debezium (Part 1): arquitectura end-to-end con Docker Compose

Si quieres entender Change Data Capture (CDC) sin quedarte en la teoría, esta demo tiene un objetivo muy concreto: mostrar cómo un cambio en una tabla de SQL Server termina convertido en un evento de Kafka usando Debezium y Kafka Connect, todo orquestado con Docker Compose.

Para que el recorrido sea claro y útil, dividí el contenido en dos partes. En esta primera parte me concentro en la arquitectura, el flujo de datos y las decisiones de diseño. En la segunda parte dejo la guía operativa para levantar la demo, validarla y probar INSERT, UPDATE y DELETE de punta a punta.

Parte 2: Cómo levantar la demo paso a paso.

Qué problema resuelve CDC

En muchos sistemas, la base de datos es la fuente de verdad y al mismo tiempo el punto donde nacen eventos valiosos para otros consumidores: analítica, sincronización con otros sistemas, motores de recomendación, pipelines de auditoría o paneles en tiempo real. El problema es que convertir cada cambio en un evento sin acoplar la aplicación no siempre es trivial.

Ahí entra CDC. En lugar de modificar la aplicación para publicar mensajes manualmente, el patrón captura los cambios desde la base de datos y los expone como un stream de eventos. En esta demo, esos eventos se publican en Kafka y luego pueden ser consumidos por distintos clientes, incluido un visor web en vivo.

Arquitectura general de la demo

La solución está compuesta por cinco servicios dentro de la red Docker cdc-net: SQL Server como origen, Kafka en modo KRaft como broker, Kafka Connect con Debezium como capa CDC, Kafka UI para inspección y un web viewer propio para visualizar eventos en tiempo real.

Arquitectura general de la demo CDC con SQL Server, Debezium, Kafka, Kafka UI y Web Viewer
Arquitectura general de la demo y relación entre servicios.

Qué hace cada componente

  • SQL Server 2022: contiene la base de datos DemoCDC y la tabla dbo.Clientes, con CDC habilitado a nivel de base y de tabla.
  • Kafka en modo KRaft: actúa como broker de eventos sin necesidad de Zookeeper, lo que simplifica mucho la demo.
  • Kafka Connect + Debezium: registra un SqlServerConnector que hace primero el snapshot inicial y luego entra en modo streaming.
  • Kafka UI: permite inspeccionar topics, mensajes y estado de connectors desde el navegador.
  • Web Viewer: es un consumidor más del topic, implementado con Node.js, KafkaJS y WebSocket para mostrar los eventos en vivo.

Un detalle importante es que el web viewer no forma parte del pipeline CDC en sí. Está desacoplado del proceso de captura y publicación; se comporta como lo haría cualquier otro consumidor real de Kafka.

Cómo fluye un cambio desde SQL Server hasta Kafka

El flujo de datos empieza con un INSERT, UPDATE o DELETE sobre dbo.Clientes. SQL Server registra ese cambio en su transaction log y, a través de los capture jobs del SQL Server Agent, lo refleja en las tablas de CDC. Debezium no hace polling con SELECT sobre la tabla de negocio: lee ese mecanismo nativo y genera un evento estructurado con metadatos de origen, operación y estado antes/después.

Flujo de datos CDC desde la tabla dbo.Clientes hasta el topic de Kafka
Del cambio en la tabla al topic de Kafka.

Ese evento se publica en el topic sqlserver.DemoCDC.dbo.Clientes. A partir de ahí, cualquier consumidor puede reaccionar: Kafka UI para inspección manual, el visor web para una demo visual o futuros sinks hacia otros sistemas.

Secuencia de operación de un UPDATE capturado por Debezium y publicado en Kafka
Secuencia de operación desde el UPDATE hasta la visualización en Kafka UI y Web Viewer.

Por qué usé Debezium y Kafka Connect

Para este caso, Debezium resuelve mejor el problema que alternativas como polling con JDBC, triggers o tablas de auditoría manuales. La ventaja principal es que aprovecha el CDC nativo de SQL Server y produce eventos ricos con before, after, op y source.

Opción Ventaja Desventaja
Debezium Captura INSERT, UPDATE y DELETE de forma no intrusiva y con eventos completos Requiere comprender Kafka Connect y la configuración del connector
Polling con JDBC Source Arranque simple No detecta bien DELETE y puede perder cambios intermedios
Triggers + auditoría Control total Acopla la lógica CDC a la base y complica mantenimiento

Además, Kafka Connect aporta una capa muy valiosa para demos y para producción: el connector se registra por JSON, queda observable por REST y se puede reiniciar, borrar o inspeccionar sin tocar código de negocio.

Por qué Kafka en modo KRaft y por qué Docker Compose

Elegí KRaft porque reduce complejidad. En una demo local, tener un contenedor menos importa: menos servicios, menos coordinación y menos puntos de fallo en el arranque. Kafka ya no necesita Zookeeper para este escenario y eso hace el stack más didáctico.

Docker Compose también fue una decisión deliberada. Permite levantar todos los componentes con un único archivo declarativo, encapsula dependencias y vuelve reproducible la demo en cualquier equipo con Docker. Para explicar CDC de forma clara, eso vale más que montar Kubernetes o un entorno más complejo desde el inicio.

Ventajas y límites de esta demo

La principal ventaja es que el flujo completo queda a la vista: base de datos, mecanismo CDC, connector, broker y consumidores. Eso hace que sea una base excelente para aprender y para enseñar el patrón.

  • Ventajas: reproducibilidad, observabilidad, separación clara de responsabilidades y un consumidor visual pensado para demos.
  • Límites: un solo broker, replicación 1, seguridad mínima, JSON con schema embebido y ausencia de un sink persistente real.

Es decir: el patrón es el correcto, pero el despliegue está optimizado para claridad y velocidad de arranque, no para tolerancia a fallos ni endurecimiento de seguridad.

Qué cambiaría en un entorno productivo

Si esta demo evolucionara a producción, el primer salto sería endurecer seguridad y disponibilidad: varios brokers Kafka, replicación mayor, TLS, autenticación, secretos gestionados y un usuario de base de datos con permisos mínimos en lugar de sa. El siguiente paso natural sería introducir Schema Registry, métricas con Prometheus + Grafana y, por supuesto, al menos un sink connector hacia un sistema analítico o de búsqueda.

También sería buena idea aplicar transformaciones SMT para aplanar eventos o enmascarar campos sensibles, según el uso posterior de los datos.

Conclusión

La idea central de esta arquitectura es simple: desacoplar el cambio en la base de datos de los sistemas que reaccionan a ese cambio. SQL Server sigue haciendo de origen transaccional; Debezium se encarga de traducir cambios a eventos; Kafka los distribuye; y consumidores como Kafka UI o el Web Viewer permiten observar el resultado casi en tiempo real.

En la segunda parte dejo la guía operativa completa: cómo levantar el stack, inicializar la base, registrar el connector, validar el snapshot y probar INSERT, UPDATE y DELETE paso a paso. Ademas de ver en un video todo esto funcionando y compartir la demo en un repo de github.

Deja un comentario