课程导入:湖仓一体与批流融合的背景、价值、核心概念与整体架构框架
1.1 数据架构演进:从数仓到湖仓一体的必然之路
过去十年间,企业数据架构经历了从传统数据仓库到数据湖,再到湖仓一体(Lakehouse)的持续演进。传统数据仓库以结构化数据为核心,依赖ETL流程将数据加工为高度建模的星型或雪花型模型,支撑BI报表与经营分析。其优势在于数据质量高、查询性能稳定,但短板同样明显:面对非结构化日志、图片、音视频等海量原始数据时,扩展成本高昂,建模周期漫长,难以支撑数据科学和机器学习场景。
数据湖的出现打破了这一僵局。以对象存储为底座的数据湖能够以近乎无限的成本优势存储任意格式的原始数据,支持“先存储、后解析”的灵活模式。然而,数据湖缺乏ACID事务保证,数据质量难以管控,且查询性能远逊于数仓,导致大量数据湖沦为“数据沼泽”。
湖仓一体架构正是为弥合上述割裂而生。它在低成本数据湖存储之上,引入事务表、元数据管理、索引与缓存等数仓核心能力,形成“一个平台、多种负载”的融合底座。其核心价值可归纳为以下四点:
- 降本增效:统一存储层消除数据冗余搬运,一份数据同时服务BI、数据科学和AI训练。
- 数据一致性:支持ACID事务,保证并发读写下的快照隔离,让湖上数据可信可用。
- 负载多样性:在同一份数据上同时运行批处理、流处理、交互式查询与机器学习。
- 开放与生态兼容:基于Parquet/ORC等开放文件格式,避免供应商锁定。
1.2 批流融合:实时与离线计算的统一编程模型
批流融合(Batch-Stream Fusion)是湖仓一体架构中处理引擎层的核心设计理念。传统Lambda架构同时维护批处理链路和流处理链路,两条代码库、两套计算引擎、两套数据口径,导致开发运维成本翻倍,且批流结果经常出现数据偏差。Kappa架构虽尝试用流处理统一一切,但在处理迟到数据、历史回放和复杂ETL时力不从心。
批流融合的实质是:用一套引擎、一套SQL/API、一套元数据语义,同时描述有界数据(批)和无界数据(流)的计算逻辑。以Apache Flink为例,其流批一体API让同一段代码既能以流模式运行(毫秒级延迟),也能以批模式运行(高吞吐全量计算),引擎层自动优化执行计划。Spark Structured Streaming同样支持基于DataFrame的统一编程接口,通过微批或持续处理模式覆盖近实时场景。
在湖仓一体框架下,批流融合进一步与存储层打通:流式写入的数据直接落为湖仓中的事务表(如Delta Lake、Iceberg、Hudi),批作业读取同一张表进行全量分析,而流作业则通过增量日志(Change Data Capture)持续消费新数据。这种“流写批读、批写流读”的闭环,让实时数仓与离线数仓共享同一份数据资产。
-- 示例:Flink SQL 中同一逻辑的批流双用
-- 流模式:从Kafka实时读取订单流
CREATE TABLE orders (
order_id BIGINT,
user_id BIGINT,
amount DECIMAL(10,2),
ts TIMESTAMP(3),
WATERMARK FOR ts AS ts - INTERVAL '5' SECOND
) WITH ('connector' = 'kafka', 'topic' = 'orders', 'properties.bootstrap.servers' = 'localhost:9092');
-- 批模式:从Hive/Iceberg读取历史订单分区
-- CREATE TABLE orders (...) WITH ('connector' = 'iceberg', 'catalog-type' = 'hive');
-- 以下聚合查询在两种模式下均可执行,引擎自动选择执行策略
SELECT user_id, SUM(amount) AS total_amount
FROM orders
GROUP BY user_id;
1.3 整体架构框架:分层解析湖仓一体数据平台
一个完整的湖仓一体批流融合平台,从下至上可分为五个逻辑层次。理解每一层的职责与接口,是设计企业级数据架构的基础。
上述架构中,存储层与计算引擎层之间的解耦是湖仓一体最具革命性的设计。事务表格式(如Iceberg)在Parquet文件之上维护表级元数据和快照,使得多个引擎(Flink、Spark、Trino)可以并发读写同一张表而互不干扰。接入层通过CDC(Change Data Capture)技术捕获数据库变更日志,实时写入湖仓表;同时,离线批量任务也可将历史数据直接导入同一张表,实现“批流同表”。
1.4 典型业务场景:实时用户画像与智能推荐
以某电商平台的用户画像与推荐系统为例,展示湖仓一体批流融合架构的实际落地路径。该平台日均产生约5亿条用户行为日志(点击、浏览、加购)和2亿条订单事件,同时维护着数亿用户的注册属性数据。
在传统Lambda架构下,团队需要维护两套代码:离线作业每30分钟调度一次,计算用户标签并写入HBase;实时作业通过Flink计算窗口内行为特征写入Redis。两套链路的数据口径经常不一致——例如离线统计的“近30天购买金额”与实时计算的“当日累计购买金额”在跨天边界时出现偏差,导致推荐系统特征混乱。
迁移至湖仓一体平台后,架构简化为以下流程:
- 统一接入:用户行为日志经Kafka实时进入Flink,以Iceberg表格式写入数据湖的
ods_user_behavior表;MySQL中的用户注册信息通过Flink CDC实时同步至dim_user维度表。 - 批流同算:实时特征计算任务(如“最近5分钟加购次数”)以Flink流模式持续运行,结果写入
dws_user_features表;离线全量标签(如“用户生命周期阶段”)以Spark批处理模式每日凌晨计算,写入同一张特征宽表的不同分区。 - 统一服务:推荐系统通过Presto查询特征宽表,或通过API服务直接读取Iceberg表的增量快照,无需再区分实时/离线数据源。
1.5 常见误区与设计复盘
在规划湖仓一体批流融合架构时,团队常陷入以下误区,值得在项目启动前充分审视:
| 误区 | 表现 | 后果 | 正确思路 |
|---|---|---|---|
| “湖仓一体=买一套新平台” | 直接采购商业湖仓产品,忽略现有技术栈兼容 | 数据迁移成本高,团队学习曲线陡峭 | 基于开源Iceberg/Delta Lake渐进式演进,复用已有Hive/Presto资产 |
| “批流融合=只用流处理” | 强制所有作业改为流模式,放弃批处理 | 复杂ETL在流模式下难以维护,成本飙升 | 根据延迟需求选择模式,同一代码逻辑双模式运行 |
| “一份数据,一个表格式” | 全公司统一使用单一表格式(如只选Hudi) | 部分引擎兼容性差,生态受限 | 根据引擎生态和场景选择,必要时支持多格式互操作 |
| “忽略数据治理” | 只关注读写性能,未建立元数据血缘和权限体系 | 数据质量失控,合规风险高 | 从第一天起就接入统一权限(Ranger)和血缘追踪 |