Apache Hudi
Section 1: Apache Hudi
Apache Hudi is an open-source data management framework used to simplify incremental data processing and data pipeline development by providing record-level insert, update, upsert, and delete capabilities. Upsert refers to the ability to insert records into an existing dataset if they do not already exist or to update them if they do. By efficiently managing how data is laid out in Amazon S3, Hudi allows data to be ingested and updated in near real time. Hudi carefully maintains metadata of the actions performed on the dataset to help ensure that the actions are atomic and consistent.
Hudi is integrated with Apache Spark, Apache Hive, Presto, Trino (from EMR 6.1.0+), and Apache Flink. With Amazon EMR release version 5.28.0 and later, Amazon EMR installs Hudi components by default when Spark, Hive, Presto, or Flink are installed. You can use Spark or the Hudi HoodieStreamer utility to create or update Hudi datasets. You can use Hive, Spark, Presto, Trino, or Flink to query a Hudi dataset written on Amazon S3. Hudi maintains the metadata of the actions performed on the Hudi dataset in index and data files, making it easy to reuse the same data for a variety of use cases.
Amazon EMR 7.12.0 ships Hudi 1.0.2, which includes a redesigned storage engine, improved indexing, non-blocking concurrency control, and a record-level metadata system. These improvements deliver significant performance gains for both read and write workloads.
Note for customers migrating from Hudi 0.x: Starting with Hudi 1.0, the DeltaStreamer ingestion utility has been renamed to HoodieStreamer. The class name, configuration prefix, and CLI entry point have all changed. If you are migrating existing pipelines from Hudi 0.x (EMR 6.x releases), update your job submission scripts and configuration files to reference org.apache.hudi.utilities.streamer.HoodieStreamer instead of the deprecated org.apache.hudi.utilities.deltastreamer.HoodieDeltaStreamer. The old class name may still work as a compatibility alias in transitional releases but is not guaranteed in future versions.
When writing datasets, Hudi supports two table types:
-
Copy on Write: Stores data in columnar format (Parquet) only. Write operations on this table result in updating the version and rewriting the files using a merge.
-
Merge on Read: Stores data in both columnar (Parquet) and row-based (Apache Avro) formats.
Write operations results in updates stored as delta files. Compactions are required to run at a scheduled frequency to arrive at new columnar files (synchronously or asynchronously).
In addition to the ability to perform upserts (updates/inserts), Hudi also provides snapshot isolation for readers (queries), atomic writes of batch of records, incremental pulls, de-duplication of data, and time travel queries.
Considerations for using Apache Hudi on Amazon EMR
Assess fit for use case
Consider using Hudi to efficiently solve the problems with incrementally ingesting data into a data lake, enforcing data privacy regulations where consumers might choose to be forgotten/erased (GDPR/CCPA), applying change data capture to data lake, bringing data freshness within minutes to your data marts on S3, and providing point-in-time views of the data in your data lake. Evaluate your use case data freshness SLA, concurrency needs, query latency and data access patterns to assess if Hudi is the right solution for your workload. Note that Hudi is not a replacement for online transactional processing (OLTP) systems and not ideal where your incoming stream of data is used in an append-only fashion (for example, dataset is primarily not mutable).
Writing Hudi datasets
Hudi provides two ways to write datasets.
-
DeltaStreamer is a utility included with Hudi that allows you to simplify the process of applying changes to Hudi data sets. DeltaStreamer is a CLI tool that can operate against three sources: Amazon S3, Apache Kafka, and Apache Hive incremental pull. (Incremental pull refers to the ability to pull only the data that changed between two actions.)
-
Spark Datasource API allows you to write your own code to ingest data from a custom source using the Spark datasource API and use a Hudi datasource to write as a Hudi dataset.
Table: Hudi write mechanisms
| DeltaStreamer | Datasource API |
|---|---|
| Use DeltaStreamer when you want a simple, self-managed ingestion tool that automates data compaction and provides automated checkpointing without the need to write any code. | Use DataSource API when you are working with several varied data sources and want to create consolidated or derived tables, for example if you have existing Spark-based ETL pipelines. |
| Need to perform transformations on ingested data, for example dropping columns, casting or filtering data. DeltaStreamer supports passing a SQL query template for SQL-based transformations. | You have existing data pipelines that need to work with both Hudi-managed and non-Hudi-managed datasets you can use the DataSource API. |
| DeltaStreamer is also a good choice if you are ingesting data from Kafka, or using AWS DMS to land files in S3 and you do not want to write any code to apply those updates. | Use Data Source API with Spark/Structured Streaming, allowing you to stream events into your Hudi dataset. |
Choosing the table type for workload
Hudi provides two storage options to choose from depending on whether your workload is read heavy (Copy on Write) or write heavy (Merge on Read). Use Copy On Write when:
-
Your job is rewriting an entire table/partition to deal with updates
-
Your workload is fairly steady and does not have sudden bursts
-
You are already using Parquet files for your tables
-
You want to keep things operationally simple, replace your existing Parquet files, and have no need for real-time views
Use Merge on Read when:
-
You want ingested data available for query as soon as possible
-
Your workload can have sudden spikes or changes in pattern
-
You want to collect the stream of changes and compact them periodically to help reduce write amplification (overhead)
Table: Comparison of Hudi table types
| Table Type | Compactions | Write Throughput | Data Freshness SLA |
|---|---|---|---|
| Copy on Write | N/A | Medium | Low |
| Merge on Read | Inline | Low | High |
| Merge on Read | Offline | High | High |