Introducción a Kafka Streams y KSQL

Última actualización: 26/08/2021

En este artículo aprenderás qué es Kafka Streams y KSQL y una introducción sobre cómo usar este motor de streaming distribuido y escalable para Apache Kafka.

Kafka Streams y KSQL

Cada vez es más común el uso del ecosistema de Apache Kafka para implementar aplicaciones en sistemas escalables de tiempo real. Este tipo de aplicaciones permiten acelerar la extracción de valor de los datos en multitud de sectores como telecomunicaciones, internet e industria.

Además, está profundamente relacionado con la infraestructura híbrida y cloud que están adoptando todas estas empresas. Es una de las plataformas que habilitan el movimiento de datos entre sistemas on-premises y cloud y que puede actuar como un clúster de agregación de eventos.

Casos de Uso de Kafka Streams

Además de sistema de procesamiento y de distribución de datos, los casos de uso para este tipo de soluciones con Apache Kafka se centran en su uso como una plataforma central de streaming de eventos. En este caso, Kafka actúa como middleware.

También se presenta como la plataforma de integración de sistemas en todos los niveles y de movimiento de datos: entre clústers, servicios, zonas, partners externos, bass de datos, aplicaciones legacy y modernas, etc.

Otro caso de uso muy extendido es el de la monitorización. Entre los tipos de monitorización en tiempo real se encuentra la monitorización de hardware, de seguridad y de servicios. Este uso permite también la implementación de alertas y actuaciones rápidas ante las anomalías detectadas.

¿Qué es Kafka Streams?

Kafka Streams es una librería open source que permite construir aplicaciones de procesamiento de flujos de datos usando Apache Kafka como sistema de almacenamiento de entrada y de salida de datos. La solución con soporte de pago la proporciona Confluent.

La versión inicial se publicó en enero del 2011 como solución de stream processing. Es posible escribir las aplicaciones en los lenguajes de programación Java y Scala. De momento, no está disponible la API de Kafka Streams para Python.

El llamado procesamiento en streaming consiste en procesar los datos de forma continua, tan pronto como están disponible para su análisis. Se procesa de manera secuencial sobre flujos de datos sin límites temporales. Esto ocurre en Kafka Streams y KSQL.

Para crear una aplicación Kafka Streams necesitaremos un clúster de Apache Kafka e insertar en un topic los datos que procesaremos con la aplicación. Para implementar una aplicación sencilla podemos importar la librería de Kafka Streams con maven en nuestro proyecto.

<!-- https://mvnrepository.com/artifact/org.apache.kafka/kafka-streams -->
<dependency>
    <groupId>org.apache.kafka</groupId>
    <artifactId>kafka-streams</artifactId>
    <version>2.8.0</version>
</dependency>

A continuación se muestra un ejemplo de aplicación Kafka Streams escrito en Java que realiza los siguientes pasos:

  1. Lee un flujo de números de un topic de Apache Kafka representados con un string y almacenados todos con la misma clave. (línea 4)
  2. Se define una ventana de tipo Tumbling de 20 segundos. Estas ventanas están basadas en intervalos de tiempos. Agrupan todos los eventos de ese intervalo, por lo que nunca se solapan. (línea 6)
  3. Suma los números de cada agrupación o ventana con la función reduce. (línea 7)
  4. Imprime los resultados por consola. (línea 9)
static String TOPIC = "TopicName";
final StreamsBuilder builder = new StreamsBuilder();
builder
 .stream(TOPIC, Consumed.with(Serdes.String(), Serdes.String()))
 .groupByKey()
 .windowedBy(TimeWindows.of(Duration.ofSeconds(20)))
 .reduce((value1, value2) -> value1 + value2)
 .toStream()
 .print(Printed.toSysOut());

Topology topology = builder.build();
final KafkaStreams streams = new KafkaStreams(topology, props); 
streams.start();

En Kafka Streams podemos realizar transformaciones con y sin estado, también llamadas stateful y stateless respectivamente.

Las transformaciones sin estado son las que no necesitan almacenamiento para llevar a cabo la operación ya que solamente usan un registro cada vez. Un ejemplo de transformación stateless es la operación branch. Esta transformación divide un stream en varios, en función de la lógica proporcionada. Otros ejemplos pueden ser la operación merge (agrupa Streams), filter (filtra elementos), group by (agrupan elementos) o Map (genera un elemento nuevo a partir de otro).

Las operaciones con estado, por el contrario, operan con varios registros a la vez o con su histórico, por lo que necesitan disponer de almacenamiento. En este conjunto de operaciones se encuentran los joins (left join, inner join, outer join), las agregaciones como count o reduce o las ventanas de procesamiento (windowing) de tipo tumbling, sliding, hopping time o de sesión

Ventajas de Kafka Streams

Es posible leer datos en tiempo real de Kafka, procesarlos y escribir de nuevo a Kafka usando las APIs de productor y consumidor.

Sin embargo, este proceso se simplifica mucho con Kafka Streams, ya que esconde la complejidad asociada a estos productores y consumidores, permitiendo centrarnos simplemente en la lógica de nuestra aplicación.

Entre las ventajas de Kafka Streams se encuentran los siguientes puntos:

  • No necesita un clúster dedicado, ya que usa Kafka
  • Permite realizar un reprocesamiento sencillo y ligero de mensajes a partir del offset
  • Desacopla fácilmente las aplicaciones (uso en microservicios)
  • Streams nativos: Procesamiento de eventos individuales
  • Garantías de entrega exactly-once
  • Facilidad de aprendizaje, con una curva sencilla para iniciados en Java
  • Procesamiento de registros tardíos y de eventos desordenados

Las limitaciones de Kafka Streams son las propias de cargas de trabajo pesadas. No es una tecnología adecuada si necesitas hacer transformaciones de datos muy complejas. Además es una tecnología totalmente acoplado a Kafka.

¿Qué es KSQL?

KSQL permite desarrollar aplicaciones de streaming sobre un sistema escalable, elástico y tolerante a fallos. Proporciona una interfaz SQL para procesamiento de flujos de datos con operaciones de filtrado, transformación, agregación y con posibilidad de usar ventanas de procesamiento. Está desarrollado por Confluent y distribuido con licencia open source.

KSQL proporciona bajas latencias, del orden de milisegundos y permite guardar el estado del sistema. Es una abstracción sobre la API de Kafka Streams que consume datos estructurados como Avro o JSON de los topics de Kafka.

Debemos diferenciar entre KStream y KTable. Son dos formas de modelar datos en Kafka Streams. Un Stream (KStream) es una secuencia de datos estructurados. Cuando un evento se añade al Stream no puede ser modificado o eliminado. Una Tabla (KTable) es mutable, y representa una situación concreta basada en el Stream de datos. Las KTables no tienen el histórico de cambios, solamente representan un estado.

Para entender esta diferencia entre KStream y KTable, nos podemos imaginar una partida de ajedrez. Un KStream podría representar la secuencia de movimientos de piezas que realizan los jugadores. Por otro lado, el estado actual de la partida o el tablero se representaría fácilmente con una KTable.

Podemos crear un Stream con el siguiente comando desde la CLI:

ksql> CREATE STREAM users_original (id bigint, user varchar) WITH (kafka_topic='users', value_format='DELIMITED'); 

También podemos crear una tabla de la siguiente forma:

ksql> CREATE TABLE users_original (registertime bigint, gender varchar, regionid varchar, userid varchar) WITH (kafka_topic='users', value_format='JSON');

Cuando manejamos tablas, también solemos querer hacer operaciones de tipo join entre varias tablas. Por ejemplo, podemos necesitar enriquecer un evento añadiéndole información disponible en una tabla que llamaremos diccionario.

Ventajas de KSQL

La gran ventaja de usar KSQL como abstracción sobre la API de Kafka Streams es que nos permite reducir la complejidad de la programación. De esta forma, podemos usar SQL, que es mucho más sencillo y amigable para programar nuestros procesadores.

Es cierto que, para transformaciones más complejas, es probable que no existan tantos detalles implementados como en Kafka Streams. Aun así, merece la pena explorar esta API y decidir por ti mismo cuál prefieres.

Kafka Streams vs Apache Flink

Ambos frameworks de procesamiento son muy populares en la actualidad. Las dos tecnologías son open source y se presentan como las mejores alternativas a Apache Spark Streaming para evitar los micro-batches y las latencias asociadas.

Apache Flink Logo

Hay que tener en cuenta que Kafka Streams (KStream) y KSQL es una API con Kafka, mientras que Apache Flink es un software completo construido desde cero como sistema de streaming de datos como objetivo. En concreto, el uso de Kafka Streams está totalmente acoplado a Kafka aunque pueda conectarse con sistemas externos. Flink también contiene integraciones (Sources y Sinks) con múltiples tecnologías y actualmente su API es más completa.

Hay que tener en cuenta que, en Kafka, si se cambia una clave, se imita el shuffle sort creando un nuevo topic, lo que disminuye el rendimiento respecto a tecnologías como Flink. Tampoco tiene checkpointing, por lo que si se caen todos los brokers puede tardar horas en recuperarse.

Siguientes Pasos con Apache Kafka

Si quieres aprender Apache Kafka a fondo y convertirte en experto, no dudes en invertir en tu formación a largo plazo. Para ello, te dejo mi propio curso en español en el que aprenderás desde cero: con partes teóricas y partes prácticas. Es un curso fundamental para quien desee implementar sistemas escalables de procesamiento de datos en tiempo real.

¡A continuación tienes un enlace con el cupón!

Comienza con Kafka: Curso de Apache Kafka desde Cero

Curso Apache Kafka

A continuación, el vídeo-resumen. ¡No te lo pierdas!


Deja una respuesta