La fundación Apache desarrolla y contribuye con una gran cantidad de proyectos para todo el ecosistema del desarrollo de software. Particularmente en el ámbito del Big Data existen 49 proyectos de características muy variadas: desde los archiconocidos Spark o Hadoop para la computación distribuida o el procesado hasta soluciones de almacenamiento de datos como Hive, pasando por frameworks menos conocidos para la transformación de datos u orquestación de procesos como Apache Beam. Será en este último en el que nos centraremos durante este artículo.
Apache Beam está concebido como un framework o modelo de programación unificado, portable y extensible. Actualmente tiene SDKs en Java, Python y Go.
El concepto de unificado en Apache Beam hace referencia a que su modelo de programación es el mismo tanto para procesados de batch (por lotes) como para procesados en streaming (continuo). Es decir, el mismo proceso (como concatenación de transformaciones) se puede aplicar a un flujo de datos por lotes o a un flujo de datos continuo, con muy pocas modificaciones.
Se dice también que es portable porque el modelo es independiente del motor de procesado sobre el que se ejecute el proceso. Este punto se trata con más detalle en la siguiente sección, pero esencialmente permite que el mismo código se ejecute sobre diferentes plataformas de procesado de datos.
Por último, es extensible porque permite ampliarlo con nuevos conectores o transformaciones de forma sencilla.
Una pieza de abstracción
Una de las características clave de Apache Beam es que está diseñado como un framework de abstracción. Es decir, nos provee un modelo “intermedio” para definir nuestro pipeline que es independiente de la plataforma sobre la que lo ejecutemos.
De esta forma nuestro mismo pipeline, con pocas (o ninguna) modificaciones puede ejecutarse en diferentes plataformas de manera sencilla. Las plataformas que soporta actualmente Apache Beam son:
- Apex: plataforma nativa de YARN que unifica procesados de streaming y batch.
- Flink: framework y engine de procesado distribuido diseñado para trabajar con procesos con estados tanto sobre flujos de datos “bounded” como “unbounded”.
- Spark: engine para el procesado y analitica de grandes cantidades de datos
- Dataflow: servicio de Google Cloud Platform para el procesamiento de datos por lotes y en streaming.
- Gearpump: engine para el procesado de eventos en tiempo real de tipo reactivo. Está basado en el modelo de Actores, y aún en incubación.
- Samza: framework distribuido de procesado de datos en streaming.
A pesar de que casi todas son proyectos de Apache, Google Cloud tiene una gran cantidad de proyectos de apache incluidos en su nube en forma de servicios, como es el caso de Dataflow. Mediante este servicio podemos abstraernos de la infraestructura necesaria para la ejecución del pipeline, y visualizar los diferentes pasos o transformaciones en tiempo real (durante la ejecución).
Conceptos básicos
Al estar pensado como un modelo abstracto, Apache beam define algunos conceptos propios para la definición de los procesos. Estos conceptos son generales y aplican a todos los SDKs.
Pipeline
En Apache Beam todo el proceso de transformaciones se encapsula en un único elemento, que es el Pipeline. Generalmente el proceso se inicia creando el pipeline, y sobre este se definen las transformaciones y las entradas y salidas de datos.
Además, en este objeto se almacenan las configuraciones generales del proceso que estarán disponibles a lo largo de nuestro código. Algunas configuraciones típicas son, por ejemplo, la localización de los datos o el formato de los mismos.
Los diferentes SDKs nos proveen también de una abstracción para poder procesar las opciones desde la propia línea de comandos.
Collections
Las colecciones (collections) representan al conjunto de datos potencialmente distribuible en Apache Beam. Es una abstracción que encapsula el conjunto de datos sobre el que se irán aplicando las diferentes transformaciones, que generarán otra collection.
En el primer paso de creación del dataset se debe utilizar un adaptador de I/O, que es un tipo concreto de transformación que nos permite la lectura o escritura de una collection. Apache Beam tiene una buena cantidad de adaptadores, pero siempre se puede desarrollar uno propio si ninguno se adapta a lo que buscamos.
Las collections tienen algunas características que es importante conocer, aunque aquí solo se recogen las más importantes:
- Tipo e inmutabilidad: una colección es inmutable, es decir, no se pueden añadir o eliminar elementos una vez creada (salvo que se cree una nueva collection). Además, todos los elementos han de ser del mismo tipo.
- Acceso aleatorio: las transformaciones tratan cada elemento de la colección de forma individual e independiente, no se puede acceder a un elemento concreto de la colección.
- Tamaño y estructura de datos: una colección es un conjunto de datos virtualmente infinita (sin tamaño máximo). Además, los datos pueden ser de tipo “bounded”, es decir, con una estructura conocida y definida; o de tipo “unbounded”, es decir, sin estructura definida.
Transformations
Las transformaciones son el concepto más amplio que tiene Apache Beam. Si las colecciones son el hilo conductor en Apache Beam, las transformaciones son los elementos que conecta ese hilo. Representan un operador genérico que se aplica a la colección de datos que llega a la misma.
El SDK provee varios tipos de transformaciones, incluido un tipo genérico (ParDo) que nos permite implementar nuestras propias funciones de transformación inspiradas en transformaciones de tipo Map/Reduce. Además, permite definir transformaciones más complejas llamadas “Composite”, que agrupan varias transformaciones sencillas.
Además, las transformaciones se pueden concatenar de dos formas: secuencial o paralela. En caso de la concatenación secuencial, cada transformación recibe la colección resultado de la transformación anterior.
Para la concatenación paralela, por el contrario, la colección resultado de la transformación original se utiliza como entrada en dos transformaciones distintas, que pueden tener procesados diferentes. Como las colecciones son inmutables, ninguna de estas transformaciones modifican esa colección de entrada, si no que generarán una nueva respectivamente. De esta forma, se pueden generar varios flujos de transformación distintos a partir de la misma colección.
Runner
El último concepto a introducir es el de runner. No forma parte estrictamente del proceso en sí, si no que nos permite definir el engine sobre el que se va a ejecutar el pipeline. Cada plataforma sobre la que se puede lanzar Apache beam tiene su propio Runner con su configuración particular, y es la única parte que se debe modificar si se quiere migrar el proceso de un engine a otro.
No es oro todo lo que reluce
Aún con todas las ventajas mencionadas anteriormente, tiene algunas desventajas que son importantes tener en cuenta. Las más importantes con las que nos hemos encontrado son la cobertura irregular de funcionalidades en los diferentes SDKs y la versión obsoleta de Python.
Un punto “negativo” de esa facilidad de extensión es que los desarrollos de los diferentes SDKs (en diferentes lenguajes) son irregulares y no siempre están al mismo nivel. El SDK con más desarrollo es el de Java, y hay algunas funcionalidades (como ciertas opciones de las ventanas en el procesado en streaming) que no están disponibles nada más que en ese lenguaje.
La versión de Python soportada en el SDK de Python, por otro lado, es la 2.7.x, que está a punto de quedar obsoleta. Es cierto que desde el proyecto están trabajando para que todas las funcionalidades actuales se soporten en Python 3 pero ahora mismo solo hay soporte oficial para Python 2.7.
Esto no quiere decir que sea una mala elección para nuestra solución, simplemente son puntos a tener en cuenta a la hora de utilizar Apache Beam en nuestro proceso de datos.
Deja tu comentario