Delta Lake es un marco de almacenamiento de código abierto que se utiliza para crear lagos de datos sobre el almacenamiento de objetos en una arquitectura Lakehouse. Delta Lake admite transacciones ACID, manejo escalable de metadatos y transmisión unificada y procesamiento de datos por lotes. Delta Lake se usa comúnmente para brindar confiabilidad, consistencia y escalabilidad a las aplicaciones de Apache Spark. Delta Lake se ejecuta sobre el almacenamiento del lago de datos existente, como MinIO, y es compatible con las API de Apache Spark.
El documento original de Delta Lake ( Delta Lake: High-Performance ACID Table Storage over Cloud Object Stores ) describe cómo se creó para el almacenamiento de objetos en la nube. Cuando Vertica probó el uso de Delta Lake para tablas externas, confiaron en MinIO. Los clientes de HPE Ezmeral Runtime Enterprise ejecutan Delta Lake en MinIO . MinIO es compatible con los requisitos de durabilidad de Delta Lake porque MinIO sigue modelos estrictos de consistencia de lectura después de escritura y lista después de escritura para todas las operaciones de E/S, tanto en modo distribuido como independiente, y es ampliamente reconocido por ejecutar cargas de trabajo de Delta Lake.
Muchas organizaciones confían en los almacenes de objetos nativos de la nube, como MinIO y AWS S3, para albergar grandes conjuntos de datos estructurados, semiestructurados y no estructurados. Cada tabla se almacena como un conjunto de objetos que son Parquet u ORC y se organizan en particiones. Las consultas sobre archivos grandes son básicamente escaneos que se ejecutan rápidamente.
Sin Delta Lake, las cargas de trabajo de Spark más complejas, en particular aquellas que modifican, agregan o eliminan datos, enfrentan desafíos de rendimiento y corrección bajo cargas pesadas de múltiples usuarios/aplicaciones. Las actualizaciones de objetos múltiples no son atómicas y las consultas no están aisladas, lo que significa que si se realiza una eliminación en una consulta, otras consultas simultáneas obtendrán resultados parciales ya que la consulta original actualiza cada objeto. Revertir las escrituras es complicado, y un bloqueo en medio de una actualización puede resultar en una tabla dañada. El verdadero asesino del rendimiento son los metadatos: para tablas masivas con millones de objetos que son archivos de Parquet que contienen miles de millones o billones de registros, las operaciones de metadatos pueden detener las aplicaciones creadas en un lago de datos.
Delta Lake fue diseñado para combinar la confiabilidad transaccional de las bases de datos con la escalabilidad horizontal de los lagos de datos. Delta Lake se creó para admitir cargas de trabajo de estilo OLAP con una capa de almacenamiento de tablas ACID sobre almacenes de objetos nativos en la nube, como MinIO. Como se describe en el artículo Delta Lake: Almacenamiento de tablas ACID de alto rendimiento sobre almacenes de objetos en la nube , “la idea central de Delta Lake es simple: mantenemos información sobre qué objetos forman parte de una tabla Delta de manera ACID, utilizando un método de escritura. registro por delante que se almacena en el almacén de objetos en la nube”. Los objetos están codificados en Parquet y pueden ser leídos por un motor que entiende Parquet. Se pueden actualizar varios objetos a la vez "de manera serializada y al mismo tiempo lograr un alto rendimiento de lectura y escritura en paralelo". El registro contiene metadatos como estadísticas mínimas/máximas para cada archivo, lo que “permite búsquedas de metadatos más rápidas en un orden de magnitud” que la búsqueda directa de archivos en el almacén de objetos.
Delta Lake proporciona lo siguiente:
La arquitectura Lakehouse, Delta Lake en particular, aporta una nueva funcionalidad clave a los lagos de datos creados en el almacenamiento de objetos. Delta Lake funciona con una lista grande y creciente de aplicaciones y motores de cómputo como Spark, Starburst, Trino, Flink y Hive, y también incluye API para Scala, Java, Rust, Ruby y Python. Creado para la nube, MinIO nativo de Kubernetes permite aplicaciones de lago de datos seguras, resilientes y de alto rendimiento en todas partes: en el perímetro, en el centro de datos y en la nube pública/privada.
Una tabla Delta es una colección de archivos que se almacenan juntos en un directorio (para un sistema de archivos) o depósito (para MinIO y otro almacenamiento de objetos). Para leer y escribir desde el almacenamiento de objetos, Delta Lake usa el esquema de la ruta para identificar dinámicamente el sistema de almacenamiento y usa la implementación de LogStore correspondiente para proporcionar garantías ACID. Para MinIO, utilizará S3A; consulte Configuración de almacenamiento: documentación de Delta Lake . Es fundamental que el sistema de almacenamiento subyacente utilizado para Delta Lake sea capaz de realizar lecturas/escrituras atómicas simultáneas, al igual que MinIO.
Crear tablas Delta es realmente escribir archivos en un directorio o depósito. Las tablas delta se crean (abren) escribiendo (leyendo) un Spark DataFrame y especificando el formato y la ruta delta
. En Scala, por ejemplo:
// Create a Delta table on MinIO: spark.range(5).write.format("delta").save("s3a://<your-minio-bucket>/<path-to-delta-table>") // Read a Delta table on S3: spark.read.format("delta").load("s3a://<your-mnio-bucket>/<path-to-delta-table>").show()
Delta Lake se basa en un depósito por tabla, y los depósitos se modelan normalmente a partir de las rutas del sistema de archivos. Una tabla de Delta Lake es un depósito que contiene datos, metadatos y un registro de transacciones. La tabla se almacena en formato Parquet. Las tablas se pueden particionar en varios archivos. MinIO es compatible con S3 LIST para listar objetos de manera eficiente utilizando rutas de estilo de sistema de archivos. MinIO también admite solicitudes de rango de bytes para leer de manera más eficiente un subconjunto de un archivo Parquet grande.
MinIO es un hogar excelente para las mesas de Delta Lake debido a su rendimiento líder en la industria. La combinación de escalabilidad y alto rendimiento de MinIO pone a su alcance todas las cargas de trabajo, sin importar cuán exigentes sean. MinIO es capaz de un rendimiento tremendo: un punto de referencia reciente logró 325 GiB/s (349 GB/s) en GET y 165 GiB/s (177 GB/s) en PUT con solo 32 nodos de SSD NVMe listos para usar. MinIO ofrece más que el rendimiento necesario para impulsar las cargas de trabajo más exigentes en Delta Lake.
Es probable que los cubos de Delta Lake contengan muchos archivos Parquet y JSON, lo que se alinea muy bien con todas las optimizaciones de archivos pequeños que hemos integrado en MinIO para usar como un lago de datos. Los objetos pequeños se guardan en línea con los metadatos, lo que reduce las IOPS necesarias para leer y escribir archivos pequeños como las transacciones de Delta Lake.
La mayoría de las empresas requieren la funcionalidad de varias nubes para Delta Lake. MinIO incluye replicación activa-activa para sincronizar datos entre ubicaciones: en las instalaciones, en la nube pública/privada y en el perímetro. La replicación activo-activo permite a las empresas diseñar la resiliencia multigeográfica y la conmutación por error rápida y activa. Cada cubo, o tabla de Delta Lake, se puede configurar para la replicación por separado para mayor seguridad y disponibilidad.
Agregar transacciones ACID (Atomicidad, Consistencia, Aislamiento y Durabilidad) a los lagos de datos es un gran problema porque ahora las organizaciones tienen un mayor control y, por lo tanto, una mayor confianza en la masa de datos almacenados en el lago de datos. Anteriormente, las empresas que confiaban en Spark para trabajar con lagos de datos carecían de API atómicas y transacciones ACID, pero ahora Delta Lake lo hace posible. Los datos se pueden actualizar después de capturarlos y escribirlos, y con la compatibilidad con ACID, los datos no se perderán si la aplicación falla durante la operación. Delta Lake logra esto actuando como intermediario entre Spark y MinIO para leer y escribir datos.
El centro de Delta Lake es DeltaLog , un registro ordenado de transacciones realizadas por usuarios y aplicaciones. Cada operación (como una ACTUALIZACIÓN o una INSERCIÓN) realizada en una tabla de Delta Lake por un usuario es una confirmación atómica compuesta de múltiples acciones o trabajos. Cuando cada acción se completa con éxito, la confirmación se registra como una entrada en DeltaLog. Si algún trabajo falla, la confirmación no se registra en DeltaLog. Sin atomicidad, los datos podrían corromperse en el caso de una falla de hardware o software que provoque que los datos solo se escriban parcialmente.
Delta Lake divide las operaciones en una o más de las siguientes acciones:
Agregar archivo: agrega un archivo
Eliminar archivo: elimina un archivo
Actualizar metadatos: registra los cambios en el nombre, el esquema o la partición de la tabla
Establecer transacción: registra que un trabajo de transmisión ha confirmado datos
Información de confirmación: información sobre la confirmación, incluida la operación, el usuario y la hora.
Cambiar protocolo: actualiza DeltaLog al protocolo de software más reciente
No es tan complicado como parece. Por ejemplo, si un usuario agrega una nueva columna a una tabla y le agrega datos, entonces Delta Lake lo desglosa en sus acciones de componentes: actualizar los metadatos para agregar la columna y agregar un archivo para cada nuevo archivo agregado, y los agrega a la DeltaLog cuando se completen.
Delta Lake se basa en el control de simultaneidad optimista para permitir que varios lectores y escritores de una tabla determinada trabajen en la tabla al mismo tiempo. El control de simultaneidad optimista supone que los cambios en una tabla realizados por diferentes usuarios pueden completarse sin conflictos. A medida que crece el volumen de datos, también aumenta la probabilidad de que los usuarios trabajen en diferentes tablas. Delta Lake serializa las confirmaciones y sigue una regla de exclusión mutua en caso de que se produzcan dos o más confirmaciones al mismo tiempo. Al hacerlo, Delta Lake logra el aislamiento requerido para ACID y la tabla tendrá el mismo aspecto después de varias escrituras simultáneas como si esas escrituras se hubieran producido en serie y por separado.
Cuando un usuario ejecuta una nueva consulta en una tabla abierta que se ha modificado desde la última vez que se leyó, Spark consulta DeltaLog para determinar si se han publicado nuevas transacciones en la tabla y actualiza la tabla del usuario con esos nuevos cambios. Esto garantiza que la versión de una tabla de un usuario esté sincronizada con la tabla maestra en Delta Lake con la operación más reciente y que los usuarios no puedan realizar actualizaciones conflictivas en una tabla.
DeltaLog, el control de concurrencia optimista y la aplicación del esquema (combinado con la capacidad de evolucionar el esquema) garantizan tanto la atomicidad como la consistencia.
Cuando un usuario crea una tabla de Delta Lake, el registro de transacciones de esa tabla se crea automáticamente en el subdirectorio _delta_log
. A medida que el usuario modifica la tabla, cada confirmación se escribe como un archivo JSON en el subdirectorio _delta_log
en orden ascendente, es decir, 000000.json
, 000001.json
, 000002.json
y así sucesivamente.
Digamos que agregamos nuevos registros a nuestra tabla desde los archivos de datos 1.parquet
y 2.parquet
. Esa transacción se agrega a DeltaLog y se guarda como el archivo 000000.json
. Más tarde, eliminamos esos archivos y agregamos un nuevo archivo 3.parquet
en su lugar. Esas acciones se registran como un nuevo archivo, 000001.json
.
Después de agregar 1.parquet
y 2.parquet
, se eliminaron. El registro de transacciones contiene ambas operaciones aunque se niegan entre sí. Delta Lake conserva todas las confirmaciones atómicas para habilitar el historial de auditoría completo y las funciones de viaje en el tiempo que muestran a los usuarios cómo se veía una tabla en un momento específico. Además, los archivos no se eliminan rápidamente del almacenamiento hasta que se ejecuta un trabajo VACÍO . El control de versiones de MinIO proporciona otra capa de garantía contra la eliminación accidental.
Delta Lake logra durabilidad al almacenar tablas y registros de transacciones en medios persistentes. Los archivos nunca se sobrescriben y deben eliminarse activamente. Todos los cambios de datos escritos en el almacenamiento están disponibles para los usuarios de forma atómica a medida que ocurren. Los archivos parciales y corruptos se vuelven cosa del pasado. Delta Lake no guarda tablas ni inicia sesión en la RAM durante mucho tiempo y las escribe directamente en MinIO. Siempre que los datos de confirmación se registraron en DeltaLog y los archivos JSON se escribieron en el depósito, los datos son duraderos en caso de que se produzca un bloqueo del sistema o del trabajo.
MinIO garantiza la durabilidad después de escribir una tabla y sus componentes a través de múltiples mecanismos:
MinIO protege las tablas de Delta Lake mediante cifrado y regula el acceso a ellas mediante una combinación de IAM y controles de acceso basados en políticas. MinIO cifra los datos en tránsito con TLS y los datos en las unidades con cifrado granular a nivel de objeto utilizando algoritmos de cifrado modernos y estándar de la industria, como AES-256-GCM, ChaCha20-Poly1305 y AES-CBC. MinIO se integra con proveedores de identidad externos como ActiveDirectory/LDAP, Okta y Keycloak para IAM. Los usuarios y grupos están sujetos a PBAC compatible con AWS IAM cuando intentan acceder a las tablas de Delta Lake.
Esta sección explica cómo comenzar rápidamente a leer y escribir tablas Delta en MinIO utilizando el modo de clúster único.
/home/spark
.hadoop-aws-2.6.5.jar
- Delta Lake necesita la clase org.apache.hadoop.fs.s3a.S3AFileSystem
del paquete hadoop-aws
, que implementa la API FileSystem
de Hadoop para S3. Asegúrese de que la versión de este paquete coincida con la versión de Hadoop con la que se creó Spark.aws-java-sdk-1.7.4.jar
Inicie Spark Shell (Scala o Python) con Delta Lake y ejecute fragmentos de código de forma interactiva.
En Scala:
bin/spark-shell --packages io.delta:delta-core_2.12:1.2.1 --conf "spark.sql.extensions=io.delta.sql.DeltaSparkSessionExtension" --conf "spark.sql.catalog.spark_catalog=org.apache.spark.sql.delta.catalog.DeltaCatalog"
Ejecute el siguiente comando para iniciar un shell de Spark con compatibilidad con Delta Lake y S3 para MinIO:
bin/spark-shell \ --packages io.delta:delta-core_2.12:1.2.1,org.apache.hadoop:hadoop-aws:3.3.1 \ --conf spark.hadoop.fs.s3a.access.key=<your-MinIO-access-key> \ --conf spark.hadoop.fs.s3a.secret.key=<your-MinIO-secret-key> --conf "spark.hadoop.fs.s3a.endpoint=<your-MinIO-IP:port> \ --conf "spark.databricks.delta.retentionDurationCheck.enabled=false" \ --conf "spark.sql.extensions=io.delta.sql.DeltaSparkSessionExtension" \ --conf "spark.sql.catalog.spark_catalog=org.apache.spark.sql.delta.catalog.DeltaCatalog"
Use MinIO Client para crear un depósito para Delta Lake:
mc alias set minio http://<your-MinIO-IP:port> <your-MinIO-access-key> <your-MinIO-secret-key> mc mb minio\delta-lake
Pruébelo y cree una tabla simple de Delta Lake usando Scala:
// Create a Delta table on MinIO: spark.range(500).write.format("delta").save("s3a://delta-lake/demo1")
Verá un resultado que indica que Spark escribió la tabla correctamente.
Abra un navegador para iniciar sesión en MinIO en http://<your-MinIO-IP:9001>
con su clave de acceso y clave secreta. Verá la tabla de Delta Lake en el cubo:
La combinación de MinIO y Delta Lake permite a las empresas tener un lago de datos de múltiples nubes que sirve como una única fuente de verdad consolidada. La capacidad de consultar y actualizar las tablas de Delta Lake brinda a las empresas información valiosa sobre sus negocios y clientes. Varios grupos acceden a las tablas de Delta Lake para sus propios análisis o iniciativas de aprendizaje automático, sabiendo que su trabajo es seguro y los datos oportunos.
Para profundizar más, descargue MinIO y compruébelo usted mismo o inicie una instancia de mercado en cualquier nube pública. ¿Tienes preguntas? Pregunte en Slack o a través de [email protected].
También publicado aquí .