Como decíamos en un artículo anterior el procesamiento en tiempo real es uno de los campos más atractivos y con más potencial dentro del panorama de BigData, siendo además, más desconocido que el procesamiento batch, por ser este el que primero despuntó en estas tecnologías. Actualmente se está viviendo una evolución del procesamiento batch al procesamiento en tiempo real (Streaming).

En este contexto, hoy traemos un artículo sobre una tecnología que supo ver el momento y nacer profundamente orientada a procesamiento streaming: Apache Flink.

 

 

Origen e historia

El origen de Flink podemos situarlo en el año 2010, en un proyecto de tratamiento de información en la nube, lanzado por el Instituto Alemán de Investigación (DFG) en colaboración con la Universidad Técnica de Berlín, la Universidad Humboldt de Berlín y el instituto Hasso-Plattner de Postdam. Estamos acostumbrados a que todas, o la mayoría de este tipo de tecnologías vengan del otro lado del Atlántico, pero Flink es un proyecto con origen en Europa.

En 2014 nace Apache Flink como tal, como un fork del proyecto anterior; momento en el que sus creadores además fundan la empresa Data Artisans, empresa encargada del soporte del mismo, con sede en Berlín. Su versión 1.0 se publicó en 2016.

El objetivo de Flink es, según sus propios creadores, cubrir la necesidad de procesamiento a gran escala, especialmente en tiempo real, manteniendo los principios del software libre y de colaboración entre la comunidad.

Hoy en dia Flink ha publicado recientemente (Diciembre 2017)  su versión 1.4 y es usado principalmente para aplicaciones que procesan información en tiempo real, pero también procesos batch, analítica de datos y machine learning en múltiples compañías a lo largo del mundo, entre los que destacan, por ejemplo Alibaba, ING o Uber.

 

Introducción

Flink no dispone de su propio sistema de almacenamiento, si no que ofrece conectores para cargar (source) y escribir (sink) datos en otros sistemas como HDFS, Kafka o Cassandra por mencionar algunos. Un programa Flink se define como un conjunto de transformaciones que se ejecutan sobre datos de origen (source) y se escriben en un destino (sink).

 

 

En procesamiento de datos, podemos definir dos tipos de datasets: finitos e infinitos. Los primeros son datasets que, como su propio nombre indica, tienen un tamaño determinado y fijo. Los segundos, son aquellos que no tienen un tamaño fijo, si no que mantienen un crecimiento sostenido en el tiempo. El auge del IoT y la tecnificación de la sociedad provoca que cada vez existan más casos de datasets infinitos (logs de aplicaciones, sensores enviando información de cualquier sistema, usuarios interactuando con sus terminales, mercados en constante movimiento etc.).

También podemos definir dos modos de ejecución: Batch y Streaming. En el primero se procesa una información dada, finita y una vez se acaba de procesar esta, finaliza. En el segundo caso, el procesamiento es constante mientras nueva información vaya siendo generada.

Cualquier tipo de dataset se puede ejecutar con cualquier tipo de ejecución, sin embargo, lo intuitivo y razonable es aplicar streaming a fuentes de datos infinitas y batch a las finitas.

Flink nace en este contexto, donde los frameworks y principios para procesamiento batch son ya ampliamente adoptados (MapReduce, Spark), orientadose a cubrir este hueco existente por y para la computación en Streaming, evitando el microbatching de otros frameworks, y siendo reactivo a la introducción de eventos en el sistema. Flink es puro Streaming.

 

APIs de Flink

De forma muy breve presentamos las diferentes API que Flink ofrece:

  • DataStream:  API para procesar Streams (infinitos)
  • DataSet: Similar a la API anterior, pero pensada para procesar dataSets (finitos)
  • Table SQL: Permite ejecutar sentencias SQL-like para tratar datasets (batch) o streams embebiendo sentencias SQL en el código. Operan sobre una abstracción de una Tabla relacional que puede ser creada desde un source o desde cualquiera de las APIs anteriores. Soporta operadores como join.

Las APIs de DataSet y de DataStream son generalmente compatibles entre sí, por lo que no implica diferentes curvas de aprendizaje, aunque lógicamente existen métodos que son específicos por la propia definición de la API (gestión de ventanas en DataStream p.e.). A continuación se muestran dos ejemplos donde se puede apreciar la similitud entre ambas APIs.

 

Principios base para analizar tecnologías BigData

 

En un anterior artículo, definíamos una serie de parámetros para analizar una tecnología de Tiempo Real BigData .A continuación los analizamos uno a uno para el caso de Flink.

Latencia

La latencia mide el tiempo que pasa desde que un evento aparece hasta que es procesado. Por lo tanto, una latencia lo más baja posible es deseable. Una buena latencia no debe estar reñida con un alto volumen de eventos procesados (throughtput).

Como mencionábamos en este mismo artículo, Flink está orientado a Streaming, por lo que no adolece de las carencias que las aplicaciones orientadas a Batch tienen, que impiden una latencia por debajo de cierto límite por las propias características de su diseño.

Flink presenta una latencia muy baja, mientras que mantiene un  throughtput elevado. Su sistema de recuperación de fallos permite mantener estos valores incluso cuando hay un error de cualquier tipo. En las gráficas siguientes puede comprobarse el throughtput de Flink comparado con otro framework (Storm), así como la latencia para diferentes niveles de throughtput.

Semántica

Con el término semántica, hacemos referencia a la posibilidad de garantizar el envío  del mensaje original, esto es la posibilidad tanto de perder eventos como duplicarlos en su procesamiento. Decíamos que había tres posibilidades en este punto:

  • at-most-once:  Asegura que no se duplican, pudiendo perderse eventos
  • at-least-once: Asegura que no se pierden, pudiendo haber duplicados
  • exactly-once: Asegura que no se pierden ni se duplican

Generalmente las tecnologías exactly-once causan aumentos de latencia, pero Flink mantiene una latencia muy baja mientras asegura exactly-once, esto es, que cada evento será procesado una única vez, sin duplicados ni pérdidas. Para ello se basa sobre todo en una potente gestión del estado.

Incluso en caso de fallo, Flink asegura exactly-once, ya que posee un mecanismo de checkpoint que en caso de fallo, permite saber exactamente hasta donde se procesó cada ventana temporal, para partir desde ese punto y evitar tanto que algún evento sea reprocesado como que alguno sea dejado atrás sin procesar. Los checkpoints se realizan de forma automática y asíncrona, no interfiriendo en el procesado de datos.

Analítica

Flink ofrece un sistema de gestión de ventanas muy flexible y con multitud de opciones.

Una ventana no es más que una agrupación de eventos de un stream infinito en grupos finitos, para facilitar su procesamiento y emisión de resultados. Para ello pueden seguirse varios principios, mediantes tipos de ventanas no-solapadas, solapadas, deslizantes etc. Esta agrupación, puede basarse en tres nociones con subcasos dentro de cada una:

Ventanas basadas en el tiempo

  1. Por Tiempo de procesamiento: Procesa los eventos durante un tiempo determinado de acuerdo con el tiempo actual del sistema.
  2.  Por Tiempo de evento: Procesa los eventos respetando el timestamp asociado a cada evento en origen, permite procesar eventos aunque lleguen desordenados o retrasados.
  3. Por Tiempo de ingesta: Semejante a tiempo de evento, pero tiene en cuenta el timestamp que le asigna a cada evento al ser recibido por el sistema en lugar del timestamp que traiga el evento desde su creación.

Ventanas basadas en conteo

Permiten definir ventanas para que procesen un número de eventos determinados

Ventanas con lógica propia

Además de los dos tipos de ventanas definidos por defecto en Flink, el framework expone las APIs de gestión y creación de ventanas para permitir al usuario definir ventanas con su propia lógica.

Ventanas deslizantes vs fijas

Flink permite dos tipos de ventana tanto para las de tiempo, como para las de conteo.

  • Fijas: Las ventanas no se solapan. Se define la duración de la ventana (en tiempo o en número de eventos en función del tipo de ventana deseada).  

Ejemplo: Ventanas de 10 segundos, ventanas de 5 elementos

  • Deslizantes: Se produce un solapamiento entre ventanas. Se define la duración de la ventana y el intervalo de inicio (de igual modo se define en tiempo o en número de eventos en función del tipo de ventana deseada)

Ejemplos: Ventanas de 10 segundos (t), con intervalo de 5 segundos (x). O ventanas de 5 eventos con intervalos de 2 eventos.

 

Referencia temporal

La referencia temporal se refiere a la noción de tiempo a considerar para cada evento.

Suelen considerarse dos referencias:

Tiempo de ingesta: Cuando el evento llega al sistema

Tiempo de evento: Cuando el evento es generado

Como vimos en el punto anterior, Flink permite operar tanto con tiempo de evento, como de ingesta,  permitiendo procesar los eventos correctamente, y otorgando resultados exactos independientemente de si llegan desordenados o incluso retrasados.

Además, la flexibilidad del sistema de ventanas analíticas, que puede basarse en tiempo o conteo, hace posible personalizar las condiciones de lanzamiento para imitar el entorno real donde los eventos estén siendo generados.

Gestión del estado

Flink asegura procesamiento statefull, esto implica que la aplicación mantiene una foto de los datos que han sido procesados en un instante de tiempo, tanto del estado interno del framework ( p.e. eventos procesados en una ventana  )  como el estado propio de la aplicación que está siendo ejecutada. Conceptos relacionados con este mecanismo son Snapshots ( automático en cada operador ) y Checkpoints ( automático a nivel de cluster ).

El mecanismo de checkpoint automático tiene una versión que se puede lanzar a demanda, llamada savepoint.  Estos savepoints, al igual que los checkpoints, son fotos estáticas del estado del procesamiento, siendo posible parar un proceso y retomarlo desde ese punto o reprocesar datos históricos sin pérdidas de datos y con un mínimo tiempo offline.

Conclusiones

Flink es uno de los grandes competidores en el escenario de BigData, especialmente para aplicaciones que requieran Streaming. La flexibilidad para trabajar con eventos independientemente del orden en que sean recibidos por el sistema, así como su compatibilidad con múltiples fuentes y destinos de datos y sus buenos niveles de latencia y  throughtput le posicionan como una amenaza muy importante para tecnologías más establecidas como Spark.

El hecho de que su API nativa sea en Java es otra ventaja importante, ya que es un lenguaje cuyo conocimiento está mucho más extendido que el de otros como Scala.

El principal reto al que se enfrenta Flink es lograr una amplia implantación comparado con otras tecnologías más asentadas en el mercado. Las mejoras que vienen en las versiones 1.4 y 1.5 aumentarán las ventajas de Flink, posibilitando una mayor implantación y mejorando por ejemplo el trabajo de networking para reducir la latencia.

 

Sergio Couto Catoira

Ingeniero Big Data en Indizen