Type something to search...
Kafka 4: Procesamiento de Datos en Tiempo Real con Kafka Streams y ksqlDB

Kafka 4: Procesamiento de Datos en Tiempo Real con Kafka Streams y ksqlDB

En los artículos anteriores, hemos construido una sólida comprensión de Apache Kafka: qué es, por qué es una plataforma líder para streaming de eventos, cómo está estructurado internamente con Topics, Particiones y Brokers, y cómo Productores y Consumidores interactúan con él para enviar y recibir datos. Tenemos nuestra “tubería central de datos” funcionando y los datos fluyendo.

Pero la verdadera potencia de una plataforma de streaming de eventos no reside solo en mover datos de un punto a otro de forma fiable y escalable, sino en la capacidad de procesar esos datos a medida que llegan, es decir, en tiempo real. Aquí es donde entran en juego las herramientas de procesamiento de stream del ecosistema Kafka.

Este artículo se centra en dos componentes clave que facilitan la construcción de aplicaciones de procesamiento de datos directamente sobre Kafka: Kafka Streams, una potente biblioteca cliente para construir aplicaciones de procesamiento de stream en Java/Scala, y ksqlDB, una base de datos de streaming que permite procesar datos en Kafka utilizando una sintaxis SQL familiar. Exploraremos cómo estas herramientas te permiten transformar, agregar, enriquecer y analizar tus flujos de eventos para derivar valor de tus datos en movimiento.

Kafka Streams: Construyendo Aplicaciones de Procesamiento de Stream

Kafka Streams es una biblioteca cliente para Java y Scala que te permite construir aplicaciones que procesan datos almacenados en Kafka. No es un framework de procesamiento distribuido separado (como Spark o Flink, aunque estos también se integran bien con Kafka), sino una API que se integra directamente en tu aplicación Java/Scala estándar. Despliegas tu aplicación de Kafka Streams como cualquier otra aplicación, y se conecta al clúster de Kafka para leer datos de Topics de entrada, aplicar lógica de procesamiento y escribir resultados en Topics de salida.

La potencia de Kafka Streams radica en su capacidad para manejar la complejidad inherente del procesamiento de stream distribuido (gestión de estado, tiempo de procesamiento, tolerancia a fallos) de una manera relativamente sencilla para el desarrollador.

image

codigo mermaid

  graph TD
      subgraph Kafka Cluster
          B[(Broker 1)]
          B2[(Broker 2)]
          B3[(Broker 3)]
      end
  subgraph Producers
      P1[Producer App 1]
      P2[Producer App 2]
  end

  subgraph Kafka Streams Application
      ST[StreamsBuilder]
      KT[KafkaStreams]
      P[Processor API]
      S[State Stores]
  end

  subgraph Consumers
      C1[Consumer App 1]
      C2[Consumer App 2]
  end

  P1 -->|publica en| B
  P2 -->|publica en| B2
  B -->|topic1| ST
  B2 -->|topic2| ST
  ST --> KT
  KT -->|procesa| P
  P -->|escribe en| S
  KT -->|escribe en| B3
  B3 -->|topic-output| C1
  B3 -->|topic-output| C2

  classDef kafka fill:#f9f,stroke:#333;
  classDef app fill:#bbf,stroke:#333;
  classDef stream fill:#9f9,stroke:#333;
  class B,B2,B3,Z kafka;
  class P1,P2,C1,C2 app;
  class ST,KT,P,S stream;

Topologías: Streams, Tablas y State Stores

Kafka Streams introduce una abstracción fundamental para representar y procesar datos:

  • Stream (KStream): Representa un flujo ilimitado de eventos inmutables. Piensa en un KStream como el log de commits de Kafka que has estado leyendo: una secuencia de eventos que ocurren a lo largo del tiempo. Cuando procesas un KStream, la lógica se aplica a cada evento individual a medida que llega.
  • Table (KTable): Representa una vista materializada de un KStream o de un Topic. A diferencia de un KStream que representa la historia completa de eventos, una KTable representa el estado actual de la clave en el momento más reciente. Por ejemplo, un KStream podría contener todos los eventos de “actualización de saldo de cuenta”, mientras que una KTable derivada de ese stream contendría el saldo actual de cada cuenta. Cuando llega un nuevo evento para una clave en un KTable, actualiza el valor existente para esa clave.
  • State Stores: Para realizar operaciones con estado (como agregaciones o joins) que requieren recordar información de eventos pasados, Kafka Streams utiliza State Stores. Son bases de datos clave-valor locales (a menudo RocksDB, aunque configurables) asociadas a cada instancia de la aplicación de Kafka Streams. El estado se gestiona localmente para cada tarea de procesamiento de la aplicación, se mantiene sincronizado con réplicas en Kafka para tolerancia a fallos y se reestablece automáticamente en caso de fallos o rebalanceos.

Esta dualidad Stream/Table es clave. Puedes convertir un KStream en un KTable (por ejemplo, para obtener el último valor por clave) y viceversa (por ejemplo, para ver un stream de cambios en una tabla).

Operaciones: map, filter, aggregate, join y Más

Kafka Streams proporciona una rica API funcional para definir la lógica de procesamiento como una topología de procesadores conectados. Algunas operaciones comunes incluyen:

  • Transformaciones sin estado: map (transforma el valor de cada registro), filter (excluye registros que no cumplen una condición), flatMap (produce cero, uno o más registros de salida por cada registro de entrada), etc.
  • Transformaciones con estado:
    • Agregaciones: groupByKey, count, reduce, aggregate. Estas operaciones acumulan o combinan valores a lo largo del tiempo para una clave específica, manteniendo el estado en un State Store.
    • Joins: join (une dos streams o un stream y una tabla basándose en una clave), leftJoin, outerJoin. Las operaciones de join a menudo requieren que uno o ambos lados del join mantengan estado (en State Stores) para poder encontrar coincidencias.
  • Ventanas (Windows): Las agregaciones y joins se realizan a menudo dentro de ventanas de tiempo (por ejemplo, contar eventos por minuto, unir eventos que ocurren en un lapso de 5 segundos). Kafka Streams soporta diferentes tipos de ventanas (ventanas de tiempo fijas, deslizantes, de sesión) y maneja la complejidad del tiempo de evento y tiempo de procesamiento.

Exactly-once Processing

Basándose en las capacidades transaccionales de Kafka (mencionadas en el Artículo 3), Kafka Streams puede ofrecer semántica de procesamiento exactly-once de extremo a extremo. Esto significa que cada evento se procesa exactamente una vez, y las actualizaciones de estado resultantes y los mensajes de salida se publican de forma atómica. Si una instancia de la aplicación falla, se reinicia y reanuda el procesamiento desde donde lo dejó sin perder ni duplicar datos, siempre y cuando los orígenes y destinos sean Topics de Kafka. Esto se habilita configurando processing.guarantee=exactly_once_v2.

KSQL (ahora ksqlDB): Streaming con Sintaxis SQL

ksqlDB (anteriormente KSQL) es una base de datos de streaming distribuida construida sobre Kafka. Permite a los desarrolladores definir aplicaciones de procesamiento de stream de forma interactiva utilizando una sintaxis similar a SQL, eliminando la necesidad de escribir código en Java o Scala para muchos casos de uso comunes.

image

codigo mermaid

    graph TD
        subgraph Kafka Cluster
            B[(Broker 1)]
            B2[(Broker 2)]
            B3[(Broker 3)]
        end
    subgraph Data Sources
        DB[(Database)]
        API[Rest API]
        IoT[IoT Devices]
    end

    subgraph ksqlDB Server
        KSQL[ksqlDB Engine]
        KQ[Queries Persistentes]
        KS[Streams]
        KT[Tables]
    end

    subgraph Consumers
        DASH[Dashboard]
        ALERTS[Alert System]
        DW[Data Warehouse]
    end

    DB -->|Debezium CDC| B
    API -->|Kafka Connect| B2
    IoT -->|MQTT Proxy| B3
    B --> KSQL
    B2 --> KSQL
    B3 --> KSQL
    KSQL -->|Crea| KS
    KSQL -->|Crea| KT
    KSQL -->|Ejecuta| KQ
    KQ -->|Escribe| B2
    B2 --> DASH
    B3 --> ALERTS
    B --> DW

    classDef kafka fill:#f9f,stroke:#333;
    classDef source fill:#f96,stroke:#333;
    classDef ksql fill:#6af,stroke:#333;
    classDef consumer fill:#6f6,stroke:#333;
    class B,B2,B3 kafka;
    class DB,API,IoT source;
    class KSQL,KQ,KS,KT ksql;
    class DASH,ALERTS,DW consumer;

ksqlDB es ideal para:

  • Transformación de datos (ETL ligero en tiempo real).
  • Enriquecimiento de datos (unir un stream de eventos con datos de referencia en una tabla).
  • Filtrado y enrutamiento de datos.
  • Agregaciones y análisis en tiempo real.
  • Creación de vistas materializadas (tablas) sobre streams de eventos.

Consultas Push/Pull

ksqlDB soporta dos tipos de consultas:

  • Consultas Push (Push Queries): Son consultas continuas que se ejecutan indefinidamente. Producen resultados en tiempo real a medida que llegan nuevos eventos a los Topics de entrada. Se usan típicamente para crear nuevos streams o tablas persistentes basadas en transformaciones, filtros o agregaciones de otros streams/tablas.
  • Consultas Pull (Pull Queries): Son consultas puntuales que se ejecutan una vez y retornan el estado actual de una tabla hasta el momento en que se ejecutó la consulta. Son útiles para obtener el valor actual de una clave o un agregado de una tabla (vista materializada).

Creación de Streams y Tablas

La sintaxis de ksqlDB es muy intuitiva para cualquiera familiarizado con SQL. Puedes definir STREAMS y TABLES sobre Topics de Kafka existentes y luego usar sentencias CREATE STREAM AS SELECT ... o CREATE TABLE AS SELECT ... para definir transformaciones continuas:

-- Crear un Stream a partir de un Topic existente
CREATE STREAM clicks (user_id VARCHAR, url VARCHAR, timestamp BIGINT)
  WITH (kafka_topic='user-clicks', value_format='json', timestamp='timestamp');

-- Filtrar y proyectar datos de un Stream y enviarlos a un nuevo Topic
CREATE STREAM high_value_clicks AS
  SELECT user_id, url
  FROM clicks
  WHERE user_id IN ('user123', 'user456');

-- Crear una Tabla (vista materializada) a partir de un Stream para contar clics por usuario
CREATE TABLE click_counts AS
  SELECT user_id, COUNT(*)
  FROM clicks
  GROUP BY user_id;

-- Realizar una consulta Pull sobre la Tabla
SELECT * FROM click_counts WHERE user_id = 'user789';

Uso en Tiempo Real (ej: Detección de Anomalías)

ksqlDB es excelente para casos de uso de tiempo real relativamente sencillos como la detección de anomalías. Por ejemplo, podrías definir una tabla que cuente el número de eventos sospechosos por usuario en una ventana de 5 minutos, y luego consultar esa tabla para alertar si el recuento excede un umbral. O podrías unir un stream de transacciones con una tabla de información de clientes para identificar transacciones inusualmente grandes para clientes nuevos.

Aunque no es tan flexible o potente como Kafka Streams para lógica de procesamiento muy compleja, ksqlDB permite a los desarrolladores y analistas de datos interactuar con Kafka y procesar streams de forma ágil utilizando una interfaz declarativa.

Conclusión

En este artículo, hemos explorado cómo ir más allá de la simple ingesta y distribución de datos en Kafka para procesarlos activamente en tiempo real. Introducimos Kafka Streams como una biblioteca robusta para construir aplicaciones de procesamiento de stream con manejo de estado y garantías exactly-once, y ksqlDB como una interfaz SQL-like accesible para realizar transformaciones y agregaciones sobre streams de forma interactiva.

Estas herramientas nativas del ecosistema Kafka empoderan a los desarrolladores para construir arquitecturas reactivas y basadas en eventos donde el procesamiento de datos ocurre continuamente a medida que los eventos fluyen, en lugar de depender de procesamiento por lotes retrasado. Ya sea que necesites construir pipelines ETL en tiempo real, aplicaciones de monitoreo o sistemas de detección de fraude, Kafka Streams y ksqlDB ofrecen las capacidades necesarias.

Ahora que tenemos una comprensión sólida de la arquitectura de Kafka, cómo interactuar con ella (Productores/Consumidores) y cómo procesar los datos en tiempo real, es momento de mirar las herramientas y plataformas que complementan a Kafka y amplían sus capacidades, así como algunas alternativas notables en el espacio del streaming de datos. En el próximo artículo, exploraremos Confluent Platform y otras herramientas clave del ecosistema Kafka.

Related Posts

Cuándo Usar Colas de Mensajes en el Desarrollo de Software

Cuándo Usar Colas de Mensajes en el Desarrollo de Software

Las colas de mensajes son herramientas clave para construir sistemas distribuidos, escalables y tolerantes a fallos. En este artículo te comparto una guía con situaciones comunes donde su uso es altam

Leer más
RabbitMQ 1: Introducción a RabbitMQ, El Corazón de la Mensajería Asíncrona

RabbitMQ 1: Introducción a RabbitMQ, El Corazón de la Mensajería Asíncrona

En el mundo del desarrollo de software moderno, especialmente con el auge de los microservicios y los sistemas distribuidos, la forma en que las diferentes partes de una aplicación se comunican es fun

Leer más
RabbitMQ 3: Configuración y Gestión de Colas en RabbitMQ

RabbitMQ 3: Configuración y Gestión de Colas en RabbitMQ

Después de entender qué es RabbitMQ y cómo sus Exchanges y Bindings dirigen los mensajes, llegamos a la Cola. La cola es fundamentalmente un buffer confiable: es el lugar donde los mensajes esperan su

Leer más
RabbitMQ 4: Robustez y Seguridad en RabbitMQ

RabbitMQ 4: Robustez y Seguridad en RabbitMQ

Hemos recorrido el camino desde la introducción a RabbitMQ y su papel en la mensajería asíncrona, pasando por su arquitectura, componentes de enrutamiento (Exchanges y Bindings), y la gestión detallad

Leer más
RabbitMQ 2: Arquitectura y Enrutamiento Avanzado en RabbitMQ

RabbitMQ 2: Arquitectura y Enrutamiento Avanzado en RabbitMQ

En nuestro primer artículo, exploramos qué es RabbitMQ, por qué es fundamental para la comunicación asíncrona en sistemas distribuidos y cuáles son sus casos de uso típicos. Lo comparamos con una "ofi

Leer más
RabbitMQ 5: Consumo de Recursos, Latencia y Monitorización de RabbitMQ

RabbitMQ 5: Consumo de Recursos, Latencia y Monitorización de RabbitMQ

Hemos explorado la teoría detrás de RabbitMQ, su arquitectura, cómo enruta mensajes y cómo podemos construir sistemas robustos y seguros. Sin embargo, para operar RabbitMQ de manera efectiva en produc

Leer más
RabbitMQ 6: Alta Disponibilidad y Escalabilidad con Clustering en RabbitMQ

RabbitMQ 6: Alta Disponibilidad y Escalabilidad con Clustering en RabbitMQ

Hasta ahora, hemos hablado de cómo un nodo individual de RabbitMQ maneja mensajes, gestiona colas, y cómo monitorizar su rendimiento y seguridad. Sin embargo, para aplicaciones críticas que no pueden

Leer más
Kafka 1: Introducción a Apache Kafka, fundamentos y Casos de Uso

Kafka 1: Introducción a Apache Kafka, fundamentos y Casos de Uso

En el panorama tecnológico actual, los datos son el motor que impulsa la innovación. La capacidad de procesar, reaccionar y mover grandes volúmenes de datos en tiempo real se ha convertido en una nece

Leer más
Kafka 2: Arquitectura Profunda de Kafka, Topics, Particiones y Brokers

Kafka 2: Arquitectura Profunda de Kafka, Topics, Particiones y Brokers

En nuestro primer artículo, despegamos en el mundo de Apache Kafka, sentando las bases de lo que es esta potente plataforma de streaming de eventos y diferenciándola de los sistemas de mensajería trad

Leer más
Kafka 3: Productores y Consumidores, Configuración y Buenas Prácticas

Kafka 3: Productores y Consumidores, Configuración y Buenas Prácticas

Hemos navegado por los conceptos esenciales de Apache Kafka y desentrañado la arquitectura que reside bajo la superficie, comprendiendo cómo los Topics se dividen en Particiones distribuidas entre Bro

Leer más
Spring WebFlux 1: Fundamentos Reactivos y el Corazón de Reactor

Spring WebFlux 1: Fundamentos Reactivos y el Corazón de Reactor

¡Hola, entusiasta del desarrollo moderno! 👋 En el vertiginoso mundo de las aplicaciones web, donde la escalabilidad y la eficiencia son reyes, ha surgido un paradigma que desafía el modelo tradicion

Leer más
Kafka 6: Despliegue, Seguridad y Optimización

Kafka 6: Despliegue, Seguridad y Optimización

Hemos explorado la arquitectura fundamental de Apache Kafka, la dinámica entre productores y consumidores, sus potentes capacidades para el procesamiento de flujos de datos y las herramientas que enri

Leer más
Spring WebFlux 2: Alta Concurrencia sin Más Hilos

Spring WebFlux 2: Alta Concurrencia sin Más Hilos

¡Bienvenido de nuevo a nuestra inmersión en Spring WebFlux! 👋 En la primera parte de esta serie, exploramos el "por qué" de la programación reactiva, entendiendo los problemas del bloqueo y descubri

Leer más
Spring WebFlux 3: Comunicación, Datos y Errores Reactivos

Spring WebFlux 3: Comunicación, Datos y Errores Reactivos

¡Continuemos nuestro viaje por el fascinante mundo de Spring WebFlux! En la Parte 1, sentamos las bases de la programación reactiva y exploramos Project Reactor, el corazón de WebFlux. En la **Pa

Leer más
Kafka 7: Patrones Avanzados y Anti-Patrones con Kafka

Kafka 7: Patrones Avanzados y Anti-Patrones con Kafka

Hemos recorrido un camino considerable en nuestra serie sobre Apache Kafka. Desde sus fundamentos y arquitectura interna hasta la interacción con productores y consumidores, las herramientas de proces

Leer más
Kafka 5: Más Allá del Core, Explorando el Ecosistema de Apache Kafka

Kafka 5: Más Allá del Core, Explorando el Ecosistema de Apache Kafka

Hemos navegado por las entrañas de Apache Kafka, comprendiendo su funcionamiento interno, la interacción entre productores y consumidores, e incluso cómo procesar datos en tiempo real con Kafka Stream

Leer más
Spring WebFlux 4: Comunicación Avanzada, Pruebas y Producción

Spring WebFlux 4: Comunicación Avanzada, Pruebas y Producción

La serie Spring WebFlux nos ha llevado a través de un viaje fascinante por el mundo de la programación reactiva, desde sus fundamentos y el poder de Project Reactor hasta la construcción de arquit

Leer más
Arquitectura DDD y Hexagonal: Construyendo Software para el Futuro

Arquitectura DDD y Hexagonal: Construyendo Software para el Futuro

En el dinámico mundo del desarrollo de software, la complejidad es el enemigo silencioso. Las aplicaciones crecen, los requisitos cambian y, sin una guía clara, el código puede convertirse rápidamente

Leer más