Capítulo 1. Conoce a Kafka

Este trabajo se ha traducido utilizando IA. Agradecemos tus opiniones y comentarios: translation-feedback@oreilly.com

Todas las empresas funcionan con datos. Recibimos información, la analizamos, la manipulamos y creamos más como resultado. Cada aplicación crea datos, ya sean mensajes de registro, métricas, actividad de los usuarios, mensajes salientes o cualquier otra cosa. Cada byte de datos tiene una historia que contar, algo de importancia que informará sobre lo siguiente que hay que hacer. Para saber qué es, tenemos que llevar los datos desde donde se crean hasta donde se pueden analizar. Lo vemos todos los días en sitios web como Amazon, donde nuestros clics en artículos que nos interesan se convierten en recomendaciones que se nos muestran un poco más tarde.

Cuanto más rápido lo hagamos, más ágiles y receptivas serán nuestras organizaciones. Cuanto menos esfuerzo dediquemos a mover los datos, más podremos centrarnos en la actividad principal. Por eso la canalización es un componente crítico en la empresa basada en datos. Cómo movemos los datos es casi tan importante como los propios datos.

Cada vez que los científicos discrepan, es porque no tenemos datos suficientes. Entonces podemos ponernos de acuerdo sobre qué tipo de datos obtener; obtenemos los datos; y los datos resuelven el problema. O yo tengo razón, o tú tienes razón, o ambos estamos equivocados. Y seguimos adelante.

Neil deGrasse Tyson

Mensajería Publicar/Suscribir

Antes de hablar de los aspectos específicos de Apache Kafka, es importante que entendamos el concepto de mensajería publicar/suscribir y por qué es un componente fundamental de las aplicaciones basadas en datos. La mensajería publicar/suscribir (pub/sub) es un patrón que se caracteriza porque el emisor (editor) de un dato (mensaje) no lo dirige específicamente a un receptor. En su lugar, el publicador clasifica el mensaje de alguna manera, y ese receptor (suscriptor) se suscribe para recibir determinadas clases de mensajes. Los sistemas pub/sub suelen tener un intermediario, un punto central donde se publican los mensajes, para facilitar este patrón.

Cómo empieza

Muchos casos de uso de publicar/suscribir empiezan de la misma manera: con una simple cola de mensajes o un canal de comunicación entre procesos. Por ejemplo, creas una aplicación que necesita enviar información de monitoreo a algún sitio, así que abres una conexión directa desde tu aplicación a una aplicación que muestre tus métricas en un panel de control, y envías métricas a través de esa conexión, como se ve en la Figura 1-1.

kdg2 0101
Figura 1-1. Un editor de métricas único y directo

Se trata de una solución sencilla a un problema sencillo que funciona cuando te estás iniciando en el monitoreo. Al poco tiempo, decides que te gustaría analizar tus métricas a más largo plazo, y eso no funciona bien en el panel de control. Creas un nuevo servicio que pueda recibir métricas, almacenarlas y analizarlas. Para soportarlo, modificas tu aplicación para escribir métricas en ambos sistemas. Ahora ya tienes tres aplicaciones más que generan métricas, y todas hacen las mismas conexiones con estos dos servicios. Tu compañero de trabajo piensa que sería una buena idea hacer también un sondeo activo de los servicios para alertar, así que añades un servidor en cada una de las aplicaciones para proporcionar métricas a petición. Al cabo de un tiempo, tienes más aplicaciones que utilizan esos servidores para obtener métricas individuales y utilizarlas con diversos fines. Esta arquitectura puede parecerse mucho a la Figura 1-2, con conexiones aún más difíciles de rastrear.

kdg2 0102
Figura 1-2. Muchos editores de métricas, utilizando conexiones directas

La deuda técnica acumulada aquí es obvia, así que decides pagar parte de ella. Configuras una única aplicación que reciba métricas de todas las aplicaciones existentes, y proporcionas un servidor que consulte esas métricas para cualquier sistema que las necesite. Esto reduce la complejidad de la arquitectura a algo similar a la Figura 1-3. Enhorabuena, ¡has construido un sistema de mensajería publicar/suscribir!

kdg2 0103
Figura 1-3. Un sistema de publicación/suscripción de métricas

Sistemas de colas individuales

Al mismo tiempo que has estado librando esta guerra con las métricas, uno de tuscompañeros de trabajo ha estado haciendo un trabajo similar con los mensajes de registro. Otro ha estado trabajando en el seguimiento del comportamiento de los usuarios en el frontend del sitio web y proporcionando esa información a los desarrolladores que están trabajando en el aprendizaje automático, así como creando algunos informes para la dirección. Todos han seguido un camino similar de construcción de sistemas que desacoplan a los editores de la información de los suscriptores de esa información. La Figura 1-4 muestra una infraestructura de este tipo, con tres sistemas pub/sub separados.

kdg2 0104
Figura 1-4. Múltiples sistemas de publicación/suscripción

Sin duda, esto es mucho mejor que utilizar conexiones punto a punto (como en la Figura 1-2), pero hay mucha duplicación. Tu empresa mantiene varios sistemas para poner datos en cola, todos ellos con sus propios fallos y limitaciones individuales. También sabes que pronto habrá más casos de uso para la mensajería. Lo que te gustaría tener es un único sistema centralizado que permita publicar tipos genéricos de datos, que irán creciendo a medida que crezca tu empresa.

Entra en Kafka

Apache Kafka se desarrolló como un sistema de mensajería de publicación/suscripción diseñado para resolver este problema. A menudo se describe como un "registro de commit distribuido" o, más recientemente, como una "plataforma de streaming distribuido". Un sistema de archivos o un registro de confirmación de una base de datos está diseñado para proporcionar un registro duradero de todas las transacciones, de modo que puedan reproducirse para construir de forma coherente el estado de un sistema. Del mismo modo, los datos de Kafka se almacenan de forma duradera, en orden, y pueden leerse de forma determinista. Además, los datos pueden distribuirse dentro del sistema para proporcionar protecciones adicionales contra fallos, así como oportunidades significativas para escalar el rendimiento.

Mensajes y lotes

La unidad de datos dentro de Kafka se denomina mensaje. Si te acercas a Kafka desde una base de datos, puedes pensar que es similar a una fila o un registro. Un mensaje es simplemente una matriz de bytes en lo que respecta a Kafka, por lo que los datos que contiene no tienen un formato o significado específico para Kafka. Un mensaje puede tener un elemento opcional de metadatos, que se denomina clave. La clave también es una matriz de bytes y, al igual que el mensaje, no tiene un significado específico para Kafka. Las claves se utilizan cuando los mensajes deben escribirse en particiones de forma más controlada. El esquema más sencillo consiste en generar un hash coherente de la clave y, a continuación, seleccionar el número de partición para ese mensaje tomando el resultado del hash módulo el número total de particiones del tema. Esto garantiza que los mensajes con la misma clave se escriban siempre en la misma partición (siempre que el recuento de particiones no cambie).

Por eficiencia, los mensajes se escriben en Kafka por lotes. Un lote no es más que una colección de mensajes, todos los cuales se producen para el mismo tema y partición. Un viaje de ida y vuelta individual a través de la red para cada mensaje supondría una sobrecarga excesiva, y reunir los mensajes en un lote la reduce. Por supuesto, se trata de un compromiso entre latencia y rendimiento: cuanto mayores sean los lotes, más mensajes se podrán gestionar por unidad de tiempo, pero más tardará un mensaje individual en propagarse. Los lotes también suelen comprimirse, lo que proporciona una transferencia y almacenamiento de datos más eficientes a costa de cierta potencia de procesamiento. Tanto las claves como los lotes se tratan con más detalle en el Capítulo 3.

Esquemas

Aunque los mensajes son matrices de bytes opacas para el propio Kafka, se recomienda imponer una estructura adicional, o esquema, al contenido del mensaje para que pueda entenderse fácilmente. Hay muchas opciones disponibles para el esquema de mensajes, dependiendo de las necesidades individuales de tu aplicación. Los sistemas simplistas, como JavaScript Object Notation (JSON) y Extensible Markup Language (XML), son fáciles de usar y legibles para las personas. Sin embargo, carecen de características como un manejo robusto de tipos y compatibilidad entre versiones de esquemas. Muchos desarrolladores de Kafka favorecen el uso de Apache Avro, que es un marco de serialización desarrollado originalmente para Hadoop. Avro proporciona un formato de serialización compacto, esquemas que están separados de las cargas útiles de los mensajes y que no requieren que se genere código cuando cambian, y una fuerte tipificación de datos y evolución de esquemas, con compatibilidad tanto hacia atrás como hacia delante.

Un formato de datos coherente es importante en Kafka, ya que permite desacoplar la escritura y la lectura de mensajes. Cuando estas tareas están estrechamente acopladas, las aplicaciones que se suscriben a los mensajes deben actualizarse para manejar el nuevo formato de datos, en paralelo con el formato antiguo. Sólo entonces pueden actualizarse las aplicaciones que publican los mensajes para utilizar el nuevo formato. Utilizando esquemas bien definidos y almacenándolos en un repositorio común, los mensajes en Kafka pueden entenderse sin coordinación. Los esquemas y la serialización se tratan con más detalle en el Capítulo 3.

Temas y Particiones

Los mensajes en Kafka se clasifican en temas. Las analogías más cercanas de un tema son una tabla de base de datos o una carpeta en un sistema de archivos. Además, los temas se dividen en varias particiones. Volviendo a la descripción del "registro de confirmación", una partición es un único registro. Los mensajes se escriben en ella de forma anexa y se leen en orden de principio a fin. Ten en cuenta que, como un tema suele tener varias particiones, no se garantiza el orden de los mensajes en todo el tema, sólo dentro de una únicapartición. La Figura 1-5 muestra un tema con cuatro particiones, con escrituras que se añaden al final de cada una. Las particiones son también la forma en que Kafka proporciona redundancia y escalabilidad. Cada partición puede alojarse en un servidor diferente, lo que significa que un tema puede escalarse horizontalmente a través de varios servidores para proporcionar un rendimiento muy superior a la capacidad de un único servidor. Además, las particiones pueden replicarse, de forma que diferentes servidores almacenen una copia de la misma partición en caso de que falle un servidor.

kdg2 0105
Figura 1-5. Representación de un tema con múltiples particiones

El término flujo se utiliza a menudo cuando se habla de datos en sistemas como Kafka. La mayoría de las veces, se considera que un flujo es un único tema de datos, independientemente del número de particiones. Esto representa un único flujo de datos que va de los productores a los consumidores. Esta forma de referirse a los mensajes es más común cuando se habla de procesamiento de flujos, que es cuando los marcos de trabajo -algunos de los cuales son Kafka Streams, Apache Samza y Storm- operan sobre los mensajes en tiempo real. Este método de funcionamiento puede compararse con la forma en que los marcos fuera de línea, en concreto Hadoop, están diseñados para trabajar con datos masivos en un momento posterior. En el Capítulo 14 se ofrece una visión general del procesamiento de flujos.

Productores y consumidores

Los clientes Kafka son usuarios del sistema, y existen dos tipos básicos: productores y consumidores. También hay API de clientes avanzados: Kafka Connect API para la integración de datos y Kafka Streams para el procesamiento de flujos. Los clientes avanzados utilizan productores y consumidores como bloques de construcción y proporcionan una funcionalidad de nivel superior en la parte superior.

Los productores crean nuevos mensajes. En otros sistemas de publicación/suscripción, pueden denominarse editores o escritores. Un mensaje se producirá para un tema concreto. Por defecto, el productor repartirá uniformemente los mensajes entre todas las particiones de un tema. En algunos casos, el productor dirigirá los mensajes a particiones específicas. Esto se hace normalmente utilizando la clave del mensaje y un particionador que generará un hash de la clave y lo asignará a una partición específica. Esto garantiza que todos los mensajes producidos con una clave determinada se escribirán en la misma partición. El productor también podría utilizar un particionador personalizado que siga otras reglas de negocio para asignar mensajes a particiones. Los productores se tratan con más detalle en el Capítulo 3.

Los consumidores leen los mensajes. En otros sistemas de publicación/suscripción, estos clientes pueden denominarse suscriptores o lectores. El consumidor se suscribe a uno o varios temas y lee los mensajes en el orden en que se produjeron a cada partición. El consumidor lleva la cuenta de los mensajes que ya ha consumido mediante el seguimiento del desplazamiento de los mensajes. El desplazamiento -unvalor entero que aumenta continuamente- es otra pieza de metadatos que Kafka añade a cada mensaje a medida que se produce. Cada mensaje de una partición determinada tiene un desplazamiento único, y el mensaje siguiente tiene un desplazamiento mayor (aunque no necesariamente monotónicamente mayor). Al almacenar el siguiente desplazamiento posible para cada partición, normalmente en el propio Kafka, un consumidor puede detenerse y reiniciarse sin perder su lugar.

Los consumidores trabajan como parte de un grupo de consumidores, que es uno o más consumidores que trabajan juntos para consumir un tema. El grupo garantiza que cada partición sólo sea consumida por un miembro. En la Figura 1-6, hay tres consumidores en un mismo grupo consumiendo un tema. Dos de los consumidores trabajan desde una partición cada uno, mientras que el tercer consumidor trabaja desde dos particiones. La asignación de un consumidor a una partición suele denominarse propiedad de la partición por parte del consumidor.

De este modo, los consumidores pueden escalar horizontalmente para consumir temas con un gran número de mensajes. Además, si falla un solo consumidor, los miembros restantes del grupo reasignarán las particiones consumidas para sustituir al miembro que falta. Los consumidores y los grupos de consumidores se tratan con más detalle en el Capítulo 4.

kdg2 0106
Figura 1-6. Un grupo de consumidores leyendo un tema

Corredores y agrupaciones

Un único servidor Kafka se denomina broker. El corredor recibe mensajes de los productores, les asigna particiones y escribe los mensajes en el almacenamiento en disco. También da servicio a los consumidores, respondiendo a las solicitudes de obtención de particiones y respondiendo con losmensajes que se han publicado. Dependiendo del hardware específico y de sus características de rendimiento, un solo corredor puede manejar fácilmente miles de particiones y millones de mensajes por segundo.

Los brokers Kafka están diseñados para funcionar como parte de un clúster. Dentro de un clúster de brokers, uno de ellos funcionará también como controlador del clúster (elegido automáticamente entre los miembros activos del clúster). El controlador es responsable de las operaciones administrativas, incluida la asignación de particiones a los corredores y el monitoreo de los fallos de los corredores. Una partición es propiedad de un único broker del clúster, y ese broker se denomina líder de la partición. Una partición replicada (como se ve en la Figura 1-7) se asigna a corredores adicionales, llamados seguidores de la partición. La replicación proporciona redundancia de mensajes en la partición, de modo que uno de los seguidores pueda asumir el liderazgo si falla un broker. Todos los productores deben conectarse al líder para publicar mensajes, pero los consumidores pueden obtenerlos del líder o de uno de los seguidores. Las operaciones de cluster, incluida la replicación de particiones, se tratan en detalle en el Capítulo 7.

kdg2 0107
Figura 1-7. Replicación de particiones en un clúster

Una característica clave de Apache Kafka es la retención, que consiste en el almacenamiento duradero de los mensajes durante cierto periodo de tiempo. Los brokers Kafka están configurados con un ajuste de retención por defecto para los temas, que retiene los mensajes durante un cierto periodo de tiempo (por ejemplo, 7 días) o hasta que la partición alcanza un cierto tamaño en bytes (por ejemplo, 1 GB). Una vez alcanzados estos límites, los mensajes caducan y se borran. De esta forma, la configuración de la retención define una cantidad mínima de datos disponibles en cada momento. Los temas individuales también pueden configurarse con sus propios ajustes de retención para que los mensajes se almacenen sólo durante el tiempo que sean útiles. Por ejemplo, un tema de seguimiento puede conservarse varios días, mientras que las métricas de la aplicación pueden conservarse sólo unas horas. Los temas también pueden configurarse como de registro compactado, lo que significa que Kafka conservará sólo el último mensaje producido con una clave específica. Esto puede ser útil para datos de tipo registro de cambios, en los que sólo interesa la última actualización.

Agrupaciones múltiples

A medida que crecen las Implementaciones de Kafka, a menudo resulta ventajoso disponer de varios clusters. Hay varias razones por las que este puede ser útil:

  • Segregación de tipos de datos

  • Aislamiento para requisitos de seguridad

  • Múltiples centros de datos (recuperación ante desastres)

En particular, cuando se trabaja con varios centros de datos, a menudo es necesario que los mensajes se copien entre ellos. De este modo, las aplicaciones online pueden tener acceso a la actividad de los usuarios en ambos sitios. Por ejemplo, si un usuario cambia la información pública de su perfil, ese cambio deberá ser visible independientemente del centro de datos en el que se muestren los resultados de la búsqueda. O bien, los datos de monitoreo pueden recopilarse de muchos sitios en una única ubicación central donde se alojen los sistemas de análisis y alerta. Los mecanismos de replicación dentro de los clusters Kafka están diseñados sólo para funcionar dentro de un único cluster, no entre varios clusters.

El proyecto Kafka incluye una herramienta llamada MirrorMaker, utilizada para replicar datos a otros clusters. En esencia, MirrorMaker es simplemente un consumidor y un productor de Kafka, unidos por una cola. Los mensajes se consumen desde un clúster Kafka y se producen hacia otro. La Figura 1-8 muestra un ejemplo de arquitectura que utiliza MirrorMaker, agregando mensajes de dos clusters locales en un cluster agregado y copiando después ese cluster a otros centros de datos. La naturaleza sencilla de la aplicación desmiente su potencia para crear sofisticados conductos de datos, que se detallarán más en en el Capítulo 9.

kdg2 0108
Figura 1-8. Arquitectura de múltiples centros de datos

¿Por qué Kafka?

Hay muchas opciones de sistemas de mensajería de publicación/suscripción, así que ¿qué hace que Apache Kafka sea una buena elección?

Múltiples productores

Kafka es capaz de manejar sin problemas múltiples productores, tanto si esos clientes utilizan muchos temas como si utilizan el mismo tema. Esto hace que el sistema sea ideal para agregar datos de muchos sistemas frontales y hacerlos coherentes. Por ejemplo, un sitio que sirve contenido a los usuarios a través de varios microservicios puede tener un único tema para las páginas vistas en el que todos los servicios puedan escribir utilizando un formato común. Las aplicaciones de consumo pueden entonces recibir un único flujo de páginas vistas para todas las aplicaciones del sitio sin tener que coordinar el consumo desde varios temas, uno para cada aplicación.

Múltiples consumidores

Además de múltiples productores, Kafka está diseñado para que múltiples consumidores puedan leer cualquier flujo de mensajes sin interferir entre sí. Esto contrasta con muchos sistemas de colas en los que, una vez que un mensaje es consumido por un cliente, no está disponible para ningún otro. Múltiples consumidores de Kafka pueden elegir operar como parte de un grupo y compartir un flujo, asegurando que todo el grupo procesa un mensaje dado sólo una vez.

Retención en disco

Kafka no sólo puede manejar múltiples consumidores, sino que la retención duradera de mensajes significa que los consumidores no siempre necesitan trabajar en tiempo real. Los mensajes se escriben en disco y se almacenarán con reglas de retención configurables. Estas opciones pueden seleccionarse por tema, lo que permite que diferentes flujos de mensajes tengan diferentes cantidades de retención en función de las necesidades del consumidor. La retención duradera significa que si un consumidor se retrasa, debido a un procesamiento lento o a una ráfaga de tráfico, no hay peligro de perder datos. También significa que se pueden realizar tareas de mantenimiento en los consumidores, desconectando las aplicaciones durante un breve periodo de tiempo, sin preocuparse de que los mensajes se acumulen en el productor o se pierdan. Los consumidores pueden detenerse, y los mensajes se conservarán en Kafka. Esto les permite reiniciarse y retomar el procesamiento de mensajes donde lo dejaron, sin pérdida de datos.

Escalable

La escalabilidad flexible de Kafka facilita el manejo de cualquier cantidad de datos. Los usuarios pueden empezar con un solo corredor como prueba de concepto, ampliar a un pequeño clúster de desarrollo de tres corredores, y pasar a producción con un clúster mayor de decenas o incluso cientos de corredores que crece con el tiempo a medida que aumentan los datos. Las ampliaciones pueden realizarse mientras el clúster está en línea, sin que ello afecte a la disponibilidad del sistema en su conjunto. Esto también significa que un clúster de múltiples intermediarios puede gestionar el fallo de un intermediario individual y seguir prestando servicio a los clientes. Los clusters que necesiten tolerar más fallos simultáneos pueden configurarse con factores de replicación más altos. La replicación se trata con más detalle en el Capítulo 7.

Alto rendimiento

Todas estas características se unen para hacer de Apache Kafka un sistema de mensajería de publicación/suscripción con un rendimiento excelente bajo cargas elevadas. Los productores, los consumidores y los intermediarios pueden ampliarse para gestionar flujos de mensajes muy grandes con facilidad. Esto puede hacerse sin dejar de proporcionar una latencia de mensajes inferior al segundo desde la producción de un mensaje hasta su disponibilidad para los consumidores.

Características de la plataforma

El núcleo del proyecto Apache Kafka también ha añadido algunas funciones de plataforma de streaming que pueden facilitar mucho a los desarrolladores la realización de tipos comunes de trabajo. Aunque no son plataformas completas, que suelen incluir un entorno de ejecución estructurado como YARN, estas funciones se presentan en forma de API y bibliotecas que proporcionan una base sólida sobre la que construir y flexibilidad en cuanto a dónde pueden ejecutarse. Kafka Connect ayuda en la tarea de extraer datos de un sistema de datos de origen e introducirlos en Kafka, o extraer datos de Kafka e introducirlos en un sistema de datos de destino. Kafka Streams proporciona una biblioteca para desarrollar fácilmente aplicaciones de procesamiento de flujos que sean escalables y tolerantes a fallos. Connect se trata en el Capítulo 9, mientras que Streams se trata con gran detalle en el Capítulo 14.

El ecosistema de datos

Muchas aplicaciones participan en los entornos que construimos para el tratamiento de datos. Hemos definido las entradas en forma de aplicaciones que crean datos o los introducen de otro modo en el sistema. Hemos definido salidas en forma de métricas, informes y otros productos de datos. Creamos bucles, en los que algunos componentes leen datos del sistema, los transforman utilizando datos de otras fuentes, y luego los introducen de nuevo en la infraestructura de datos para utilizarlos en otro lugar. Esto se hace para numerosos tipos de datos, cada uno con cualidades únicas de contenido, tamaño y uso.

Apache Kafka proporciona el sistema circulatorio para el ecosistema de datos, como se muestra en la Figura 1-9. Transporta mensajes entre los distintos miembros de la infraestructura, proporcionando una interfaz coherente para todos los clientes. Cuando se acopla con un sistema para proporcionar esquemas de mensajes, los productores y consumidores ya no necesitan un acoplamiento estrecho ni conexiones directas de ningún tipo. Los componentes pueden añadirse y eliminarse a medida que se crean y disuelven casos empresariales, y los productores no tienen que preocuparse de quién utiliza los datos ni del número de aplicaciones consumidoras.

kdg2 0109
Figura 1-9. Un ecosistema de big data

Casos prácticos

Seguimiento de la actividad

El caso de uso original de Kafka, tal y como se diseñó en LinkedIn, es el del seguimiento de la actividad de los usuarios. Los usuarios de un sitio web interactúan con aplicaciones frontales, que generan mensajes sobre las acciones que está realizando el usuario. Puede tratarse de información pasiva, como páginas vistas y seguimiento de clics, o de acciones más complejas, como la información que un usuario añade a su perfil. Los mensajes se publican en uno o varios temas, que luego son consumidos por aplicaciones en el backend. Estas aplicaciones pueden generar informes, alimentar sistemas de aprendizaje automático, actualizar los resultados de las búsquedas o realizar otras operaciones necesarias para proporcionar una experiencia de usuario enriquecida.

Mensajería

Kafka también se utiliza para mensajería, cuando las aplicaciones necesitan enviar notificaciones (como correos electrónicos) a los usuarios. Esas aplicaciones pueden producir mensajes sin necesidad de preocuparse del formato o de cómo se enviarán realmente los mensajes. Una sola aplicación puede entonces leer todos los mensajes que se van a enviar y gestionarlos de forma coherente, incluyendo:

  • Formatear los mensajes (también conocido como decorar) utilizando un aspecto común

  • Reunir varios mensajes en una sola notificación para enviarla

  • Aplicar las preferencias de un usuario sobre cómo quiere recibir mensajes

Utilizar una única aplicación para ello evita la necesidad de duplicar funciones en varias aplicaciones, además de permitir operaciones como la agregación, que de otro modo no serían posibles.

Métricas y registro

Kafka también es ideal para recopilar métricas y registros de aplicaciones y sistemas. Este es un caso de uso en el que brilla la capacidad de tener varias aplicaciones que producen el mismo tipo de mensaje. Las aplicaciones publican métricas de forma regular en un tema de Kafka, y esas métricas pueden ser consumidas por los sistemas para el monitoreo y las alertas. También pueden utilizarse en un sistema fuera de línea como Hadoop para realizar análisis a más largo plazo, como proyecciones de crecimiento. Los mensajes de registro pueden publicarse del mismo modo y dirigirse a sistemas dedicados de búsqueda de registros, como Elasticsearch, o a aplicaciones de análisis de seguridad. Otra ventaja añadida de Kafka es que cuando hay que cambiar el sistema de destino (por ejemplo, es hora de actualizar el sistema de almacenamiento de registros), no es necesario alterar las aplicaciones frontales ni los medios de agregación.

Registro de compromiso

Como Kafka se basa en el concepto de registro de cambios, los cambios de la base de datos pueden publicarse en Kafka, y las aplicaciones pueden monitorizar fácilmente este flujo para recibir actualizaciones en directo a medida que se producen. Este flujo de registro de cambios también puede utilizarse para replicar las actualizaciones de la base de datos a un sistema remoto, o para consolidar los cambios de varias aplicaciones en una única vista de la base de datos. La retención duradera es útil aquí para proporcionar un búfer para el registro de cambios, lo que significa que puede reproducirse en caso de fallo de las aplicaciones consumidoras. Alternativamente, se pueden utilizar temas de registro compactado para proporcionar una retención más larga al retener sólo un cambio por clave.

Tratamiento de flujos

Otra área que proporciona numerosos tipos de aplicaciones es el procesamiento de flujos. Aunque casi todo el uso de Kafka puede considerarse procesamiento de flujos, el término se utiliza normalmente para referirse a aplicaciones que proporcionan una funcionalidad similar al procesamiento map/reduce en Hadoop. Hadoop suele basarse en la agregación de datos durante un largo periodo de tiempo, ya sean horas o días. El procesamiento de flujos opera sobre los datos en tiempo real, tan rápido como se producen los mensajes. Los marcos de procesamiento de flujos permiten a los usuarios escribir pequeñas aplicaciones para operar sobre mensajes Kafka, realizando tareas como el recuento de métricas, la partición de mensajes para un procesamiento eficiente por parte de otras aplicaciones, o la transformación de mensajes utilizando datos de múltiples fuentes. El procesamiento de flujos se trata en el Capítulo 14.

El origen de Kafka

Kafka se creó para abordar el problema de la canalización de datos en LinkedIn. Se diseñó para proporcionar un sistema de mensajería de alto rendimiento que pudiera manejar muchos tipos de datos y proporcionar datos limpios y estructurados sobre la actividad de los usuarios y las métricas del sistema en tiempo real.

Los datos realmente impulsan todo lo que hacemos.

Jeff Weiner, ex consejero delegado de LinkedIn

El problema de LinkedIn

De forma similar al ejemplo descrito al principio de este capítulo, LinkedIn tenía un sistema para recopilar métricas del sistema y de las aplicaciones que utilizaba recopiladores personalizados y herramientas de código abierto para almacenar y presentar los datos internamente. Además de las métricas tradicionales, como el uso de la CPU y el rendimiento de la aplicación, había una sofisticada función de seguimiento de solicitudes que utilizaba el sistema de monitoreo y podía proporcionar una introspección de cómo se propagaba una solicitud de un solo usuario a través de las aplicaciones internas. Sin embargo, el sistema de monitoreo tenía muchos fallos. Entre ellos, la recopilación de métricas basada en sondeos, grandes intervalos entre métricas y ninguna capacidad para que los propietarios de las aplicaciones gestionaran sus propias métricas. El sistema era muy táctil, requería la intervención humana para la mayoría de las tareas sencillas, y era incoherente, con diferentes nombres de métricas para la misma medición en los distintos sistemas.

Al mismo tiempo, se creó un sistema de seguimiento de la información sobre la actividad de los usuarios. Se trataba de un servicio HTTP al que los servidores frontales se conectaban periódicamente y publicaban un lote de mensajes (en formato XML) en el servicio HTTP. A continuación, estos lotes se trasladaban a plataformas de procesamiento fuera de línea, que era donde se analizaban y cotejaban los archivos. Este sistema tenía muchos fallos. El formato XML era incoherente, y analizarlo era costoso desde el punto de vista informático. Cambiar el tipo de actividad del usuario que se rastreaba requería una cantidad significativa de trabajo coordinado entre los frontales y el procesamiento fuera de línea. Incluso entonces, el sistema se rompía constantemente debido a los cambios en los esquemas. El seguimiento se basaba en lotes horarios, por lo que no podía utilizarse en tiempo real.

El monitoreo y el seguimiento de la actividad de los usuarios no podían utilizar el mismo servicio backend. El servicio de monitoreo era demasiado tosco, el formato de los datos no estaba orientado al seguimiento de la actividad, y el modelo de sondeo para el monitoreo no era compatible con el modelo push para el seguimiento. Al mismo tiempo, el servicio de seguimiento era demasiado frágil para utilizarlo para las métricas, y el procesamiento por lotes no era el modelo adecuado para el monitoreo y las alertas en tiempo real. Sin embargo, los datos de monitoreo y seguimiento compartían muchos rasgos, y la correlación de la información (como la forma en que determinados tipos de actividad de los usuarios afectaban al rendimiento de la aplicación) era muy deseable. Un descenso en tipos concretos de actividad de los usuarios podía indicar problemas con la aplicación que le daba servicio, pero horas de retraso en el procesamiento de los lotes de actividad significaban una respuesta lenta a este tipo de problemas.

Al principio, se investigaron a fondo las soluciones de código abierto existentes para encontrar un nuevo sistema que proporcionara acceso en tiempo real a los datos y se ampliara para gestionar la cantidad de tráfico de mensajes necesaria. Se crearon sistemas prototipo con ActiveMQ, pero en aquel momento no podía manejar la escala. También era una solución frágil para la forma en que LinkedIn necesitaba utilizarla, y se descubrieron muchos fallos en ActiveMQ que provocaban pausas en los brokers. Estas pausas retrasarían las conexiones con los clientes e interferirían con la capacidad de las aplicaciones para servir peticiones a los usuarios. Se tomó la decisión de seguir adelante con una infraestructura personalizada para la canalización de datos.

El nacimiento de Kafka

El equipo de desarrollo de LinkedIn estaba dirigido por Jay Kreps, un ingeniero de software principal que anteriormente había sido responsable del desarrollo y la publicación en código abierto de Voldemort, un sistema de almacenamiento distribuido de valores clave. El equipo inicial también incluía a Neha Narkhede y, más tarde, a Jun Rao. Juntos, se propusieron crear un sistema de mensajería que pudiera satisfacer las necesidades de los sistemas de monitoreo y seguimiento, y escalar para el futuro. Los objetivos principales eran

  • Desacoplar a productores y consumidores utilizando un modelo push-pull

  • Proporcionar persistencia para los datos de los mensajes dentro del sistema de mensajería para permitir que varios consumidores

  • Optimizar para un alto flujo de mensajes

  • Permitir el escalado horizontal del sistema para crecer a medida que crecían los flujos de datos

El resultado fue un sistema de mensajería de publicación/suscripción que tenía una interfaz típica de los sistemas de mensajería, pero una capa de almacenamiento más parecida a un sistema de agregación de registros. Combinado con la adopción de Apache Avro para la serialización de mensajes, Kafka resultó eficaz para gestionar tanto las métricas como el seguimiento de la actividad de los usuarios a una escala de miles de millones de mensajes al día. La escalabilidad de Kafka ha ayudado a que el uso de LinkedIn crezca por encima de los siete billones de mensajes producidos (en febrero de 2020) y más de cinco petabytes de datos consumidos diariamente.

Código abierto

Kafka se publicó como proyecto de código abierto en GitHub a finales de 2010. Cuando empezó a ganar atención en la comunidad de código abierto, fue propuesto y aceptado como proyecto incubador de la Apache Software Foundation en julio de 2011. Apache Kafka salió de la incubadora en octubre de 2012. Desde entonces, se ha trabajado continuamente en él y ha encontrado una sólida comunidad de colaboradores y committers fuera de LinkedIn. Kafka se utiliza ahora en algunos de los mayores conductos de datos del mundo, como los de Netflix, Uber y muchas otras empresas.

La adopción generalizada de Kafka también ha creado un ecosistema saludable en torno al proyecto central. Hay grupos de encuentro activos en docenas de países de todo el mundo, que proporcionan debates locales y apoyo al procesamiento de flujos. También hay numerosos proyectos de código abierto relacionados con Apache Kafka. LinkedIn sigue manteniendo varios, como Cruise Control, Kafka Monitor y Burrow. Además de sus ofertas comerciales, Confluent ha publicado proyectos como ksqlDB, un registro de esquemas y un proxy REST bajo una licencia comunitaria (que no es estrictamente de código abierto, ya que incluye restricciones de uso). Varios de los proyectos más populares se enumeran en el Apéndice B.

Compromiso comercial

En otoño de 2014, Jay Kreps, Neha Narkhede y Jun Rao dejaron LinkedIn para fundar Confluent, una empresa centrada en proporcionar desarrollo, soporte empresarial y formación para Apache Kafka. También se unieron a otras empresas (como Heroku) en la prestación de servicios en la nube para Kafka. Confluent, a través de una asociación con Google, proporciona clusters gestionados de Kafka en Google Cloud Platform, así como servicios similares en Amazon Web Services y Azure. Otra de las principales iniciativas de Confluent es organizar la serie de conferencias Kafka Summit. Iniciada en 2016, con conferencias celebradas anualmente en Estados Unidos y Londres, Kafka Summit proporciona un lugar para que la comunidad se reúna a escala mundial y comparta conocimientos sobre Apache Kafka y proyectos relacionados.

El nombre

A menudo la gente pregunta cómo obtuvo Kafka su nombre y si significa algo específico sobre la propia aplicación. Jay Kreps ofreció la siguiente perspectiva:

Pensé que, puesto que Kafka era un sistema optimizado para la escritura, utilizar el nombre de un escritor tendría sentido. Había asistido a muchas clases de literatura en la universidad y me gustaba Franz Kafka. Además, el nombre sonaba bien para un proyecto de código abierto.

Así que básicamente no hay mucha relación.

Primeros pasos con Kafka

Ahora que sabemos todo sobre Kafka y su historia, podemos configurarlo y construir nuestra propia canalización de datos. En el próximo capítulo, exploraremos la instalación y configuración de Kafka. También trataremos la selección del hardware adecuado para ejecutar Kafka, y algunas cosas a tener en cuenta al pasar a operaciones de producción.

Get Kafka: La Guía Definitiva, 2ª Edición now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.