El conector integrado de Hudi ya no será compatible en versiones futuras de Ververica Runtime (VVR). Utilice custom connectors para conectar Realtime Compute for Apache Flink con Apache Hudi, o migre a Paimon connector para obtener funciones y rendimiento optimizados.
Apache Hudi es un framework de data lake de código abierto que gestiona datos tabulares almacenados en Object Storage Service (OSS) o Hadoop Distributed File System (HDFS). Ofrece garantías ACID (Atomicidad, Consistencia, Aislamiento, Durabilidad), operaciones upsert y delete a nivel de fila, gestión automática de archivos pequeños y consultas de viaje en el tiempo.
Funciones principales
|
Función |
Descripción |
|
Semántica ACID |
Aislamiento de instantáneas de forma predeterminada, lo que garantiza la consistencia de los datos durante lecturas y escrituras simultáneas. |
|
Semántica UPSERT |
Combina INSERT y UPDATE: si un registro no existe, se inserta; si ya existe, se actualiza. Esto simplifica el código de desarrollo ETL. |
|
Viaje en el tiempo |
Permite acceder a versiones históricas de datos en un momento específico, lo que facilita la auditoría eficiente de datos y el control de calidad. |
Escenarios típicos
|
Escenario |
Descripción |
|
Aceleración de ingesta de bases de datos |
Escriba datos de Change Data Capture (CDC) (por ejemplo, registros binarios de MySQL mediante el conector MySQL CDC) directamente en una tabla Hudi para procesos ETL en tiempo real posteriores; esta opción es más rentable que la carga masiva sin conexión. |
|
ETL incremental |
Extraiga flujos de datos de cambios de Hudi de forma incremental para realizar procesos ETL ligeros y en tiempo real. Utilice Apache Presto o Apache Spark para análisis OLAP posteriores. |
|
Colas de mensajes |
Utilice Hudi como reemplazo ligero de colas de mensajes para escenarios de bajo volumen, lo que simplifica la arquitectura de la aplicación. |
|
Relleno de datos |
Combine datos completos e incrementales de tablas Hudi en un metastore de Hive para generar tablas anchas con una sobrecarga de cómputo mínima. |
Ventajas sobre Hudi de código abierto
Sin mantenimiento: El conector integrado de Hudi reduce la complejidad de operación y mantenimiento, y ofrece garantías de SLA.
Mayor conectividad de datos: Desacopla los datos de los motores de cómputo, lo que permite una migración fluida entre Apache Flink, Apache Spark, Apache Presto y Apache Hive.
Ingesta simplificada de base de datos a lago: Funciona con el conector Flink CDC para agilizar el desarrollo de datos.
Funciones de clase empresarial: Gestión unificada de metadatos mediante Data Lake Formation (DLF) y cambios de esquema ligeros automáticos.
Almacenamiento rentable: Los datos se almacenan en formato Apache Parquet o Apache Avro en Alibaba Cloud OSS, con aislamiento de almacenamiento y cómputo para un escalado flexible de recursos.
Configuraciones compatibles
|
Elemento |
Valor |
|
Tipo de tabla |
Tabla de origen, tabla de destino |
|
Modo de ejecución |
Modo streaming, modo por lotes |
|
Formato de datos |
N/A |
|
Tipo de API |
DataStream API, SQL API |
|
Actualización/eliminación de datos en destino |
Compatible |
|
Versión mínima de VVR |
vvr-4.0.11-flink-1.13 |
|
Sistemas de archivos compatibles |
OSS, HDFS, OSS-HDFS |
Métricas
|
Tipo de tabla |
Métricas |
|
Tabla de origen |
|
|
Tabla de destino |
|
Para consultar las definiciones de las métricas, véase Métricas.
Limitaciones
Versión mínima del motor: vvr-4.0.11-flink-1.13 o posterior.
Sistemas de archivos compatibles: únicamente OSS, HDFS u OSS-HDFS.
Los trabajos en borrador no pueden ejecutarse en clústeres de sesión.
El conector de Hudi no admite modificaciones de campos. Para modificar campos, utilice sentencias Spark SQL en la consola de Data Lake Formation (DLF).
Sintaxis
CREATE TEMPORARY TABLE hudi_tbl (
uuid BIGINT,
data STRING,
ts TIMESTAMP(3),
PRIMARY KEY(uuid) NOT ENFORCED
) WITH (
'connector' = 'hudi',
'path' = 'oss://<yourOSSBucket>/<Custom storage directory>',
...
);
Parámetros en la cláusula WITH
Parámetros básicos
Parámetros comunes
|
Parámetro |
Obligatorio |
Predeterminado |
Descripción |
|
|
Sí |
— |
Establézcalo en |
|
|
Sí |
— |
Ruta de almacenamiento de la tabla. Formatos compatibles: OSS ( |
|
|
No |
|
Campo de clave primaria. Separe varios campos con comas. Como alternativa, utilice la sintaxis |
|
|
No |
|
Campo de versión utilizado para determinar el orden de las actualizaciones. Si no se establece, las actualizaciones siguen la secuencia de mensajes definida por el motor. |
|
|
No |
— |
Obligatorio cuando se almacenan datos en OSS u OSS-HDFS. Para endpoints de OSS, consulte Regions and endpoints. Para endpoints de OSS-HDFS, consulte la sección Port de la página Overview del bucket de OSS. |
|
|
No |
— |
AccessKey ID. Obligatorio para OSS y OSS-HDFS. Almacene las credenciales como variables en lugar de codificarlas directamente. Consulte Manage variables. |
|
|
No |
— |
AccessKey secret. Obligatorio para OSS y OSS-HDFS. |
Para proteger su par de AccessKey, almacene el AccessKey ID y el AccessKey secret como variables. Consulte Gestionar variables.
Parámetros de tabla de origen
|
Parámetro |
Obligatorio |
Predeterminado |
Descripción |
|
|
No |
|
Establézcalo en |
|
|
No |
(vacío) |
Desplazamiento inicial para la lectura en streaming. Formato: |
Parámetros de tabla de destino
|
Parámetro |
Obligatorio |
Predeterminado |
Descripción |
|
|
No |
|
Modo de escritura. Valores válidos: |
|
|
No |
|
Establézcalo en |
|
|
No |
|
Modo de sincronización. |
|
|
No |
|
Nombre de la base de datos Hive de destino. |
|
|
No |
Nombre de la tabla actual |
Nombre de la tabla Hive de destino. No debe contener guiones ( |
|
|
No |
— |
Región donde está activado DLF. Solo surte efecto cuando |
|
|
No |
— |
Endpoint de DLF. Solo surte efecto cuando |
Parámetros avanzados
Parámetros de paralelismo
|
Parámetro |
Predeterminado |
Descripción |
|
|
|
Paralelismo de las tareas de escritura. Cada tarea escribe secuencialmente en uno o más buckets. Aumentar este valor no incrementa la cantidad de archivos pequeños. |
|
|
Paralelismo del despliegue |
Paralelismo de los operadores de asignación de buckets. Aumentar este valor incrementa la cantidad de archivos pequeños. |
|
|
Paralelismo del despliegue |
Paralelismo de los operadores de arranque de índice. Solo surte efecto cuando |
|
|
|
Paralelismo de los operadores de lectura en streaming y por lotes. |
|
|
|
Paralelismo de los operadores de compactación en línea. La compactación en línea consume más recursos que la compactación sin conexión; prefiera la compactación sin conexión para cargas de trabajo de producción. |
Parámetros de compactación en línea
|
Parámetro |
Predeterminado |
Descripción |
|
|
|
Indica si se generan planes de compactación según una programación. Mantenga este valor en |
|
|
|
Indica si la compactación se ejecuta de forma asíncrona. Establézcalo en |
|
|
|
Paralelismo de las tareas de compactación. |
|
|
|
Estrategia utilizada para activar la compactación. Valores válidos: |
|
|
|
Número de commits necesarios para activar la compactación. Se usa con |
|
|
|
Intervalo en segundos entre activaciones de compactación. Se usa con |
|
|
|
Memoria máxima para el mapa hash utilizado durante la compactación y la deduplicación. Auméntela a 1 GB si los recursos lo permiten. |
|
|
|
Rendimiento máximo de E/S por plan de compactación. |
Parámetros de tamaño de archivo
Estos parámetros controlan cómo Hudi gestiona los tamaños de archivo para evitar la acumulación de archivos pequeños.
|
Parámetro |
Predeterminado |
Descripción |
|
|
120 MB (120 × 1024 × 1024 bytes) |
Tamaño máximo de un archivo Parquet. Los datos que superen este umbral se escriben en un nuevo grupo de archivos. |
|
|
100 MB (104,857,600 bytes) |
Los archivos menores a este umbral se consideran archivos pequeños. Durante la escritura, Hudi anexa datos a los archivos pequeños existentes en lugar de crear nuevos. |
|
|
1 KB (1,024 bytes) |
Tamaño estimado del registro. Si no se establece, Hudi calcula este valor dinámicamente a partir de los metadatos confirmados. |
Parámetros de configuración de Hadoop
|
Parámetro |
Predeterminado |
Descripción |
|
|
— |
Elementos de configuración de Hadoop, especificados con el prefijo |
Parámetros de escritura de datos
Escritura por lotes
Utilice la escritura por lotes para importar datos existentes de otras fuentes a una tabla Hudi.
bulk_insertomite la serialización Avro, la compactación y la deduplicación. Garantice la unicidad de los datos de origen antes de usar este modo.bulk_insertsolo es válido en el modo de ejecución por lotes.
|
Parámetro |
Predeterminado |
Descripción |
|
|
|
Tipo de escritura. Establézcalo en |
|
|
Paralelismo del despliegue |
Paralelismo para las tareas de |
|
|
|
Indica si se reorganizan los datos de entrada por campo de partición antes de escribir. Disponible en Hudi 0.11.0 y posteriores. Reduce la cantidad de archivos pequeños, pero puede causar sesgo de datos. |
|
|
|
Indica si se ordenan los datos de entrada por campo de partición antes de escribir. Disponible en Hudi 0.11.0 y posteriores. Reduce la cantidad de archivos pequeños cuando una sola tarea escribe en varias particiones. |
|
|
|
Memoria gestionada disponible para el operador de ordenamiento, en MB. |
Modo changelog
En el modo changelog, Hudi conserva todos los eventos de cambio (INSERT, UPDATE_BEFORE, UPDATE_AFTER y DELETE), lo que permite implementar almacenamiento de datos casi en tiempo real de extremo a extremo con la computación con estado de Flink. Las tablas Merge On Read (MOR) admiten este modo.
En el modo sin changelog, los cambios intermedios dentro de un lote se fusionan. La lectura de instantáneas devuelve solo el resultado final fusionado; los estados intermedios no son visibles independientemente de la ruta de escritura.
Después de habilitar el modo changelog, la tarea de compactación asíncrona sigue fusionando los cambios intermedios. Establezca compaction.delta_commits=5 y compaction.delta_seconds=3600 para dar a los consumidores posteriores tiempo suficiente para leer los registros antes de que se compacten.
|
Parámetro |
Predeterminado |
Descripción |
|
|
|
Establézcalo en |
Modo anexar
Compatible con Hudi 0.10.0 y posteriores.
Tablas MOR: Se aplica la política de archivos pequeños. Los datos se escriben en archivos de registro Apache Avro en modo anexar.
Tablas Copy On Write (COW): No se aplica la política de archivos pequeños. Se crea un nuevo archivo Apache Parquet para cada escritura.
Parámetros de clustering
Hudi admite clustering para resolver la acumulación de archivos pequeños en modo INSERT.
Clustering en línea (solo tablas COW)
|
Parámetro |
Predeterminado |
Descripción |
|
|
|
Establézcalo en |
Clustering asíncrono (Hudi 0.12.0 y posteriores)
|
Parámetro |
Predeterminado |
Descripción |
|
|
|
Establézcalo en |
|
|
|
Número de commits necesarios para generar un plan de clustering. Solo surte efecto cuando |
|
|
|
Establézcalo en |
|
|
|
Paralelismo de las tareas de clustering. |
|
|
1 GiB (1,073,741,824 bytes) |
Tamaño máximo de archivo objetivo para la salida del clustering. |
|
|
|
Los archivos menores a este umbral (en bytes) son elegibles para clustering. |
|
|
— |
Columnas utilizadas para ordenar datos durante el clustering. |
Estrategias de plan de clustering
|
Parámetro |
Predeterminado |
Descripción |
|
|
|
Modo de filtro de partición. Valores válidos: |
|
|
|
Número de días recientes para seleccionar particiones para clustering. Solo surte efecto cuando |
|
|
— |
Partición inicial para filtrado por rango. Solo surte efecto cuando |
|
|
— |
Partición final para filtrado por rango. Solo surte efecto cuando |
|
|
— |
Expresión regular para seleccionar particiones. |
|
|
— |
Lista separada por comas de particiones seleccionadas. |
Elegir un tipo de índice
Hudi admite dos tipos de índice. Utilice esta tabla para elegir el que mejor se adapte a su carga de trabajo.
|
Dimensión |
FLINK_STATE |
BUCKET |
|
Sobrecarga de almacenamiento/cómputo |
Sí (backend de estado) |
Ninguna |
|
Rendimiento |
Depende del backend de estado |
Mejor (sin sobrecarga de estado) |
|
Flexibilidad de grupos de archivos |
Asigna registros dinámicamente según el tamaño del archivo |
Número fijo de buckets (no se puede aumentar después de la configuración inicial) |
|
Cambios entre particiones |
Compatible |
No compatible (excepción: entrada streaming de Change Data Capture (CDC)) |
|
Cuándo utilizarlo |
Tablas con menos de 500 millones de registros, o cargas de trabajo que requieren actualizaciones entre particiones |
Tablas con más de 500 millones de registros donde la sobrecarga de estado es un cuello de botella |
Cuandoindex.typese establece enBUCKET, establecerindex.global.enabled=trueno tiene efecto, ya que el índice de bucket no admite deduplicación entre particiones.
|
Parámetro |
Predeterminado |
Descripción |
|
|
|
Tipo de índice. Valores válidos: |
|
|
Clave primaria |
Campo de clave hash para el índice de bucket. Puede ser un subconjunto de la clave primaria. |
|
|
|
Número de buckets por partición. No se puede cambiar después de crear la tabla. |
Los parámetros de índice de bucket son compatibles con Hudi 0.11.0 y posteriores.
Parámetros de lectura de datos
Hudi admite tres patrones de lectura utilizando el mismo conjunto de parámetros.
|
Patrón |
Configuración |
|
Lectura en streaming |
Establezca |
|
Lectura incremental por lotes |
Establezca tanto |
|
Viaje en el tiempo |
Establezca solo |
Parámetros de lectura en streaming
De forma predeterminada, la lectura de una tabla Hudi utiliza lectura de instantáneas, devolviendo la última instantánea completa de una vez. Establezca read.streaming.enabled=true para cambiar a lectura en streaming.
|
Parámetro |
Predeterminado |
Descripción |
|
|
|
Establézcalo en |
|
|
(vacío) |
Desplazamiento inicial. Formato: |
|
|
|
Número máximo de commits históricos retenidos por el limpiador. Los commits que superen este límite se eliminan. Por ejemplo, con un intervalo de puntos de control de 5 minutos, el valor predeterminado de 30 retiene los changelogs durante al menos 150 minutos. |
La lectura en streaming de changelogs requiere Hudi 0.10.0 o posterior. Las tareas de compactación pueden fusionar changelogs, eliminando registros intermedios y afectando potencialmente los cálculos posteriores.
Parámetros de lectura incremental
|
Parámetro |
Predeterminado |
Descripción |
|
|
Último commit |
Inicio del rango de lectura, en formato |
|
|
Último commit |
Fin del rango de lectura, en formato |
Ejemplos
Tabla de origen
CREATE TEMPORARY TABLE blackhole (
id INT NOT NULL PRIMARY KEY NOT ENFORCED,
data STRING,
ts TIMESTAMP(3)
) WITH (
'connector' = 'blackhole'
);
CREATE TEMPORARY TABLE hudi_tbl (
id INT NOT NULL PRIMARY KEY NOT ENFORCED,
data STRING,
ts TIMESTAMP(3)
) WITH (
'connector' = 'hudi',
'oss.endpoint' = '<yourOSSEndpoint>',
'accessKeyId' = '${secret_values.ak_id}',
'accessKeySecret' = '${secret_values.ak_secret}',
'path' = 'oss://<yourOSSBucket>/<Custom storage directory>',
'table.type' = 'MERGE_ON_READ',
'read.streaming.enabled' = 'true'
);
-- Read from the latest commit in streaming mode and write to Blackhole.
INSERT INTO blackhole SELECT * FROM hudi_tbl;
Tabla de destino
CREATE TEMPORARY TABLE datagen (
id INT NOT NULL PRIMARY KEY NOT ENFORCED,
data STRING,
ts TIMESTAMP(3)
) WITH (
'connector' = 'datagen',
'rows-per-second' = '100'
);
CREATE TEMPORARY TABLE hudi_tbl (
id INT NOT NULL PRIMARY KEY NOT ENFORCED,
data STRING,
ts TIMESTAMP(3)
) WITH (
'connector' = 'hudi',
'oss.endpoint' = '<yourOSSEndpoint>',
'accessKeyId' = '${secret_values.ak_id}',
'accessKeySecret' = '${secret_values.ak_secret}',
'path' = 'oss://<yourOSSBucket>/<Custom storage directory>',
'table.type' = 'MERGE_ON_READ'
);
INSERT INTO hudi_tbl SELECT * FROM datagen;
DataStream API
Para utilizar DataStream API, configure un conector DataStream para Realtime Compute for Apache Flink. Consulte Settings of DataStream connectors.
Dependencias de Maven
Ajuste las versiones de las dependencias a su versión de VVR.
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<flink.version>1.15.4</flink.version>
<hudi.version>0.13.1</hudi.version>
</properties>
<dependencies>
<!-- Flink -->
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-streaming-java</artifactId>
<version>${flink.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-table-common</artifactId>
<version>${flink.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-table-api-java-bridge</artifactId>
<version>${flink.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-table-planner_2.12</artifactId>
<version>${flink.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-clients</artifactId>
<version>${flink.version}</version>
<scope>provided</scope>
</dependency>
<!-- Hudi -->
<dependency>
<groupId>org.apache.hudi</groupId>
<artifactId>hudi-flink1.15-bundle</artifactId>
<version>${hudi.version}</version>
<scope>provided</scope>
</dependency>
<!-- OSS -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>3.3.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-aliyun</artifactId>
<version>3.3.2</version>
<scope>provided</scope>
</dependency>
<!-- DLF -->
<dependency>
<groupId>com.aliyun.datalake</groupId>
<artifactId>metastore-client-hive2</artifactId>
<version>0.2.14</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-mapreduce-client-core</artifactId>
<version>2.5.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
Las dependencias de DLF entran en conflicto con las versiones de código abierto de Apache Hive (hive-common, hive-exec). Para pruebas locales de DLF, descargue los paquetes JAR personalizados hive-common y hive-exec e impórtelos manualmente en IntelliJ IDEA.
Escribir datos en Hudi
El siguiente ejemplo escribe datos en una tabla Hudi MOR en OSS y, opcionalmente, sincroniza metadatos con DLF.
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.table.data.GenericRowData;
import org.apache.flink.table.data.RowData;
import org.apache.flink.table.data.StringData;
import org.apache.hudi.common.model.HoodieTableType;
import org.apache.hudi.configuration.FlinkOptions;
import org.apache.hudi.util.HoodiePipeline;
import java.util.HashMap;
import java.util.Map;
public class FlinkHudiQuickStart {
public static void main(String[] args) throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
String dbName = "test_db";
String tableName = "test_tbl";
String basePath = "oss://xxx";
Map<String, String> options = new HashMap<>();
// Hudi configuration
options.put(FlinkOptions.PATH.key(), basePath);
options.put(FlinkOptions.TABLE_TYPE.key(), HoodieTableType.MERGE_ON_READ.name());
options.put(FlinkOptions.PRECOMBINE_FIELD.key(), "ts");
options.put(FlinkOptions.DATABASE_NAME.key(), dbName);
options.put(FlinkOptions.TABLE_NAME.key(), tableName);
// OSS configuration
// Use the public endpoint for local debugging (e.g., oss-cn-hangzhou.aliyuncs.com)
// Use the internal endpoint for cluster submission (e.g., oss-cn-hangzhou-internal.aliyuncs.com)
options.put("hadoop.fs.oss.accessKeyId", "xxx");
options.put("hadoop.fs.oss.accessKeySecret", "xxx");
options.put("hadoop.fs.oss.endpoint", "xxx");
options.put("hadoop.fs.AbstractFileSystem.oss.impl", "org.apache.hadoop.fs.aliyun.oss.OSS");
options.put("hadoop.fs.oss.impl", "org.apache.hadoop.fs.aliyun.oss.AliyunOSSFileSystem");
// DLF configuration (optional — remove if not syncing to DLF)
// Use the public endpoint for local debugging (e.g., dlf.cn-hangzhou.aliyuncs.com)
// Use the VPC endpoint for cluster submission (e.g., dlf-vpc.cn-hangzhou.aliyuncs.com)
options.put(FlinkOptions.HIVE_SYNC_ENABLED.key(), "true");
options.put(FlinkOptions.HIVE_SYNC_MODE.key(), "hms");
options.put(FlinkOptions.HIVE_SYNC_DB.key(), dbName);
options.put(FlinkOptions.HIVE_SYNC_TABLE.key(), tableName);
options.put("hadoop.dlf.catalog.id", "xxx");
options.put("hadoop.dlf.catalog.accessKeyId", "xxx");
options.put("hadoop.dlf.catalog.accessKeySecret", "xxx");
options.put("hadoop.dlf.catalog.region", "xxx");
options.put("hadoop.dlf.catalog.endpoint", "xxx");
options.put("hadoop.hive.imetastoreclient.factory.class",
"com.aliyun.datalake.metastore.hive2.DlfMetaStoreClientFactory");
DataStream<RowData> dataStream = env.fromElements(
GenericRowData.of(StringData.fromString("id1"), StringData.fromString("name1"), 22,
StringData.fromString("1001"), StringData.fromString("p1")),
GenericRowData.of(StringData.fromString("id2"), StringData.fromString("name2"), 32,
StringData.fromString("1002"), StringData.fromString("p2"))
);
HoodiePipeline.Builder builder = HoodiePipeline.builder(tableName)
.column("uuid string")
.column("name string")
.column("age int")
.column("ts string")
.column("`partition` string")
.pk("uuid")
.partition("partition")
.options(options);
// Second parameter: whether the input stream is bounded (true = batch, false = streaming)
builder.sink(dataStream, false);
env.execute("Flink_Hudi_Quick_Start");
}
}