1. Flink 对 Hive 的两种整合方式,到底怎么选
1.1 HiveCatalog:把 Hive Metastore 当 Flink 的元数据底座
你可以把 Flink 的表定义存到 Hive Metastore 里,例如把 Kafka / Elasticsearch / JDBC 表注册进 HMS,后续任何 Flink SQL 会话只要 USE CATALOG 就能直接用,不用每次 CREATE TABLE。
适用场景
- 多个作业/多个团队共享一套表定义
- 需要统一的数据资产管理(库表、分区、权限、血缘等)
- 你希望 Flink SQL 开发体验更像"数据仓库"(而不是脚本式建表)
1.2 Flink 直接读写 Hive 表:Hive 表变成 Flink 的 Source/Sink
Flink 可以把 Hive 表当作普通表来 INSERT/SELECT,适合:
- Kafka 流式写 Hive 分区表(入仓)
- Hive 表作为维度表或离线明细表进行补数、回放
- Flink 批处理替代一部分 Hive/Spark 任务
一句选择建议
- 你想"复用元数据、像数仓一样管理表",优先 HiveCatalog
- 你想"把 Hive 表作为落地/读取目标",就用 Flink 读写 Hive 表(通常也会配合 HiveCatalog)
2. 版本支持与关键限制(提前知道,少走弯路)
Flink 支持的 Hive 版本范围(按你贴的文档)
- 2.3 系列:2.3.0 到 2.3.10
- 3.1 系列:3.1.0 到 3.1.3
一些"不是 Flink 的锅"的 Hive 版本差异
- Hive 内置函数:Hive 1.2.0+ 才完整
- 表约束(PRIMARY KEY、NOT NULL):Hive 3.1.0+ 才支持
- 写 ORC:Hive 2.0.x 不支持(如果你落 ORC 表,务必确认 Hive 版本)
还有一个非常现实的信息
- Flink 2.2 暂时没有"现成的 connector 包"随发行版带上,需要你自己把 Hive 相关 jar 放到 Flink 的 classpath(SQL Client 或集群 lib)
3. 依赖怎么放才不冲突:推荐"整包 connector",别手搓一堆 jar
3.1 必须先解决 Hadoop 依赖
Hive 建在 Hadoop 上,Flink 想连 Hive,Hadoop 的类一定要在 classpath 里。
最常用方式:设置 HADOOP_CLASSPATH
bash
export HADOOP_CLASSPATH=`hadoop classpath`
同时建议把 Hadoop 配置也准备好(生产更推荐)
- 环境变量:HADOOP_CONF_DIR 指向包含 core-site.xml、hdfs-site.xml 的目录
- 或在 HiveCatalog 里显式配置 hadoop-conf-dir(仅本地路径)
3.2 Hive 依赖两种方式:强烈推荐"bundled jar"
方式 A:使用 Flink 打好的 Hive 整包(推荐)
-
对应 Hive Metastore 版本直接选一个
- 2.3.0--2.3.10:flink-sql-connector-hive-2.3.10
- 3.0.0--3.1.3:flink-sql-connector-hive-3.1.3
-
把下载的 jar 放到 Flink 的 lib 目录(或 SQL Client 用 -l/-C 加到 classpath)
方式 B:自己拼 jar(不推荐,除非整包不满足)
典型例子(Hive 2.3.4)需要至少这些
- flink-connector-hive_2.12-2.2.0.jar
- hive-exec-2.3.4.jar
- 如果要 Hive dialect:antlr-runtime-3.5.2.jar
手搓方式最容易出现的坑
- Guava、Jackson、Calcite、Hadoop 依赖版本冲突
- 你本地能跑,集群一跑就 ClassNotFound 或 NoSuchMethod
结论:能用整包就用整包。
4. 最小可跑 Demo:SQL Client 接入 HiveCatalog
下面给你一个"复制就能跑"的 SQL 流程(你只要改 hive-site.xml 路径/默认库名)。
4.1 准备 hive-site.xml
把 hive-site.xml 放到某个目录,例如
- /opt/hive-conf/hive-site.xml
保证其中 metastore 连接信息正确(thrift URI、数据库连接等)
4.2 在 Flink SQL Client 里创建 HiveCatalog
sql
CREATE CATALOG myhive WITH (
'type' = 'hive',
'default-database' = 'mydatabase',
'hive-conf-dir' = '/opt/hive-conf'
);
USE CATALOG myhive;
可选项说明(常用)
- hive-version:一般不要填,让 Flink 自动探测;除非探测失败
- hadoop-conf-dir:如果你不想用 HADOOP_CONF_DIR,可以在这里给本地路径
4.3 切 Hive Dialect 来执行 Hive DDL(推荐)
Hive 的 DDL(建表、分区、函数等)最好用 Hive dialect 执行,兼容性更好。
sql
SET 'table.sql-dialect' = 'hive';
然后就可以用更 Hive 的方式建库建表(示例)
sql
CREATE DATABASE IF NOT EXISTS ods;
USE ods;
CREATE TABLE IF NOT EXISTS t_user (
id BIGINT,
name STRING,
age INT
)
STORED AS PARQUET;
执行完 Hive DDL 后,如果你还要跑 Flink 的一些语法特性,也可以切回默认 dialect:
sql
SET 'table.sql-dialect' = 'default';
5. 用 Flink 写 Hive 表:从 DataGen 造数入仓(无 Kafka 也能演示)
5.1 造一个 DataGen 源表(本地压测/联调神器)
sql
CREATE TABLE gen_user (
id BIGINT,
name STRING,
age INT
) WITH (
'connector' = 'datagen',
'rows-per-second' = '1000',
'fields.id.kind' = 'sequence',
'fields.id.start' = '1',
'fields.id.end' = '1000000',
'fields.age.min' = '1',
'fields.age.max' = '80'
);
5.2 写入 Hive 表
sql
INSERT INTO ods.t_user
SELECT id, name, age FROM gen_user;
如果是分区表(更常见),你会经常这么写:
sql
SET 'table.sql-dialect' = 'hive';
CREATE TABLE IF NOT EXISTS ods.t_user_pt (
id BIGINT,
name STRING,
age INT
)
PARTITIONED BY (dt STRING)
STORED AS PARQUET;
SET 'table.sql-dialect' = 'default';
INSERT INTO ods.t_user_pt
SELECT id, name, age, DATE_FORMAT(CURRENT_TIMESTAMP, 'yyyy-MM-dd') AS dt
FROM gen_user;
6. HiveCatalog 的"隐藏爽点":把 Kafka/ES 表也存进 HMS,跨会话复用
很多人第一次用 HiveCatalog 只拿来读写 Hive 表,其实它更大的价值是"统一注册表定义"。
比如你建一个 Kafka 表、一个 ES 表,直接 CREATE TABLE 在 HiveCatalog 下,那么这俩表的定义就进了 HMS,别的 Flink 会话可以直接用,无需重复建表。
大概长这样(示意,参数按你环境补齐):
sql
USE CATALOG myhive;
USE mydatabase;
CREATE TABLE kafka_orders (
order_id BIGINT,
user_id BIGINT,
amount DOUBLE,
ts TIMESTAMP(3),
WATERMARK FOR ts AS ts - INTERVAL '5' SECOND
) WITH (
'connector' = 'kafka',
...
);
CREATE TABLE ods_orders (
order_id BIGINT,
user_id BIGINT,
amount DOUBLE
)
STORED AS PARQUET;
之后任何会话只要 USE CATALOG myhive 就能直接 SELECT/INSERT。
7. 最常见的 6 类报错与解决思路(生产必踩)
- 找不到 Hadoop 类 / 读不到 HDFS
典型:ClassNotFound、No FileSystem for scheme hdfs
解决
- 确认 HADOOP_CLASSPATH 生效
- 确认 HADOOP_CONF_DIR 指向正确目录(core-site.xml、hdfs-site.xml)
- Hive Metastore 连不上
典型:MetaException、TTransportException
解决
- hive-site.xml 的 metastore uris 是否正确
- 网络/防火墙/端口是否通
- metastore 服务是否启动、版本是否匹配
- Hive 版本探测失败
解决
- 先不要手填 hive-version,让它自动探测
- 如果确实失败,再显式指定 hive-version(并确保你放的 connector jar 对应这个版本段)
- Dialect 不对导致 DDL 语法报错
解决
- 建 Hive 表、分区、函数建议用 hive dialect
- Flink 特有语法/函数再切回 default
- Jar 冲突(最烦)
典型:NoSuchMethodError、ClassCastException
解决
- 优先使用 Flink 提供的 bundled hive connector jar
- 尽量不要混用多套 hive-exec/hadoop 版本
- 集群上 classpath 顺序要固定(lib 里重复 jar 是灾难)
- ORC 写入失败
解决
- 确认 Hive 版本(2.0.x 不支持写 ORC)
- 优先 Parquet 跑通链路再上 ORC
8. 一套落地建议:从"能跑"到"能用"
- 开发环境先用 DataGen + Hive 表,把链路打通
- 统一把 connector jar 管理到一处(Flink lib 或统一的 classpath 目录)
- Hive DDL 用 hive dialect,业务查询再用 default dialect
- 分区表写入时,尽量明确分区字段生成逻辑,避免"分区乱飞"
- 如果你还要做性能压测,建议你用我前面那套"Print 验证正确性 + BlackHole 测吞吐上限"的闭环,把 Hive 外部写入成本与 SQL 计算成本拆开看