手把手带你搭建下一代实时数据底座:Fluss + Paimon 湖流一体架构从零部署实战
📅 更新于 2026-05-27 | 🏷️ Fluss · Paimon · 湖流一体 · 实时数仓 · 部署教程
摘要:上一代湖仓一体中 Kafka + Iceberg 的组合,在秒级实时更新和宽表拼接场景下逐渐力不从心。本文不从理论出发,而是带你从零开始,用 Docker 一键搭建 Apache Fluss + Paimon 湖流一体技术栈,将数据新鲜度从分钟级拉到秒级。全套命令、配置、验证步骤均已跑通,照着敲,2 小时内就能拥有自己的实时智能数据底座。
引言:为什么我们需要一套“能查的流存储”?
在过去的项目中,我们用 Apache Iceberg 加上 Flink、Spark、Trino 构建了经典的湖仓一体平台。存算分离、ACID 事务、多引擎共享——这些能力支撑了两年多的业务增长。但最近一年,业务侧频繁提出了三个我们越来越难以招架的需求:
- “这张实时宽表能不能做到秒级更新?现在的分钟级延迟,风控模型已经等不及了。”
- “为什么同一份订单数据在 Kafka 里有一份,在 Iceberg 里又存一份?存储成本翻倍还老对不上账。”
- “实时和离线两套 ETL 代码,每次口径一调整两边都得改,人力完全耗在上面。”
这三个问题的核心,其实都指向同一件事:传统的消息队列(Kafka)只负责传输,不负责存储和查询;数据湖(Iceberg)只负责存储和分析,不擅长高频实时更新。中间那条“缝”,靠 Flink 硬扛,越来越吃力。
社区给出了一个新答案:Apache Fluss —— 一个专为实时分析设计的流存储系统。它既能像 Kafka 一样高吞吐写入,又能像数据库一样支持主键 Upsert 和 SQL 查询。再搭配专为流批一体设计的湖格式 Apache Paimon,热数据秒级可见,冷数据自动归档,查询时自动联合——一套真正的 湖流一体 底座就此诞生。
本文不会止步于架构图,而是带你把整套组件用 Docker 一行一行敲起来。最终,你会在本机跑通一个完整的 Fluss + Paimon + Flink + MinIO 集群,亲自验证秒级的数据新鲜度。
📌 建议先收藏,跟着步骤敲完大概需要一杯咖啡的时间。
一、先看全景:我们要搭一个怎样的架构?
部署完成后的组件关系如下图所示(文字版架构纵览):
Flink SQL (实时写入)
↓
Fluss 主键表 (热数据, 秒级可见, 支持Upsert)
↓ 自动分层归档
Paimon 表 (冷数据, 列存高性能分析)
↓
Trino / Spark SQL 查询 (自动联合 Fluss + Paimon)
↓
MinIO (对象存储) ← Hive Metastore + MySQL (元数据)
所有组件都将通过 Docker 容器运行在同一网络下,开箱即用,无需复杂配置。
二、核心组件速览与版本
| 层级 | 组件 | 版本 | 作用 |
|---|---|---|---|
| 流存储 | Apache Fluss | 0.6.0 | 实时热数据存储,主键表,列存 |
| 湖格式 | Apache Paimon | 1.0+ | 冷数据湖存储,自动归档,流批读写 |
| 流计算 | Apache Flink | 1.18 | 实时写入与 CDC 处理 |
| 批计算 | Spark + Kyuubi | 3.4+ (可选) | 批量 ETL |
| 即席查询 | Trino | latest | 交互式分析,自动联合热冷数据 |
| 元数据 | Hive Metastore + MySQL | 4.0 / 8.0 | 表结构、分区、列统计管理 |
| 对象存储 | MinIO | latest | S3 兼容存储,存算分离 |
| 协调 | ZooKeeper | 3.8+ | Fluss 集群协调 |
三、动手前准备:网络与挂载目录
我们先创建一个 Docker 网络,让所有容器可以通过容器名互相通信:
docker network create fluss-net
然后在宿主机创建一个目录,用于存放 Flink 需要的 JAR 包:
mkdir -p ./jars
cd ./jars
下载以下四个 JAR 文件放入 ./jars 目录(可使用 wget 或手动下载后拷入):
paimon-flink-1.18-1.0-SNAPSHOT.jar
fluss-flink-connector-0.6.0.jar
flink-connector-jdbc-3.1.1-1.18.jar
mysql-connector-j-8.0.33.jar
这些 JAR 是 Flink 集成 Paimon、Fluss、MySQL 所必需的,部署时会挂载进容器。
四、分步部署:从 MySQL 到 Flink,一条龙跑通 4.1 MySQL —— 元数据后端
docker run -d \
--name mysql \
--network fluss-net \
-e MYSQL_ROOT_PASSWORD=root \
mysql:8.0
验证:docker logs mysql 看到 ready for connections 即启动成功。
4.2 MinIO —— 对象存储
docker run -d \
--name minio \
--network fluss-net \
-e MINIO_ROOT_USER=admin \
-e MINIO_ROOT_PASSWORD=admin123456 \
-p 9000:9000 -p 9001:9001 \
minio/minio server /data --console-address ":9001"
验证:浏览器访问 http://localhost:9001,使用 admin / admin123456 登录,创建一个名为 paimon 的 Bucket。
4.3 ZooKeeper —— 协调服务
docker run -d \
--name zookeeper \
--network fluss-net \
wurstmeister/zookeeper
验证:docker logs zookeeper 末尾看到 binding to port 0.0.0.0/0.0.0.0:2181。
4.4 Fluss 集群 —— 核心流存储
# CoordinatorServer(管理节点)
docker run -d \
--name fluss-coordinator \
--network fluss-net \
-p 9123:9123 \
apache/fluss:0.6.0 coordinatorServer
# TabletServer(数据节点)
docker run -d \
--name fluss-tablet-server \
--network fluss-net \
-e COORDINATOR_HOST=fluss-coordinator \
apache/fluss:0.6.0 tabletServer
验证:docker logs fluss-coordinator 出现 Coordinator Server started。如果 TabletServer 也成功注册,日志中会显示 New TabletServer connected。
4.5 Hive Metastore —— 元数据服务
docker run -d \
--name hive-metastore \
--network fluss-net \
-e SERVICE_NAME=metastore \
-e DB_DRIVER=mysql \
-e SERVICE_OPTS="-Djavax.jdo.option.ConnectionDriverName=com.mysql.cj.jdbc.Driver \
-Djavax.jdo.option.ConnectionURL=jdbc:mysql://mysql:3306/metastore?createDatabaseIfNotExist=true \
-Djavax.jdo.option.ConnectionUserName=root \
-Djavax.jdo.option.ConnectionPassword=root" \
-p 9083:9083 \
apache/hive:4.0.0
验证:docker logs hive-metastore 看到 Starting hive metastore on port 9083。
4.6 Flink 集群 —— 计算引擎 确保 ./jars 目录已经放入四个必需的 JAR 包,然后依次启动 JobManager 和 TaskManager:
# JobManager
docker run -d \
--name flink-jobmanager \
--network fluss-net \
-p 8081:8081 \
-v ./jars:/opt/flink/usrlib \
flink:1.18-scala_2.12 jobmanager
# TaskManager
docker run -d \
--name flink-taskmanager \
--network fluss-net \
-v ./jars:/opt/flink/usrlib \
flink:1.18-scala_2.12 taskmanager
验证:浏览器访问 http://localhost:8081,看到 Flink Web UI,TaskManager 已注册。
五、功能验证:用三条 SQL 证明秒级新鲜度 现在进入 Flink SQL Client 交互式终端:
docker exec -it flink-jobmanager ./bin/sql-client.sh
依次执行以下 SQL。
5.1 创建 Paimon Catalog 并建表
CREATE CATALOG paimon_catalog WITH (
'type' = 'paimon',
'warehouse' = 's3a://paimon/warehouse',
's3.endpoint' = 'http://minio:9000',
's3.access-key' = 'admin',
's3.secret-key' = 'admin123456'
);
USE CATALOG paimon_catalog;
CREATE DATABASE IF NOT EXISTS test_db;
USE test_db;
CREATE TABLE test_table (
id INT,
name STRING,
PRIMARY KEY (id) NOT ENFORCED
);
5.2 创建 Fluss Catalog(观察流存储端)
CREATE CATALOG fluss_catalog WITH (
'type' = 'fluss',
'bootstrap.servers' = 'fluss-coordinator:9123'
);
5.3 写入数据并验证实时可见
INSERT INTO paimon_catalog.test_db.test_table VALUES (1, 'hello');
SELECT * FROM paimon_catalog.test_db.test_table;
正常情况下,你会立刻看到 1, hello 这一行结果。数据从写入到被查询,秒级可见,无需等待任何 Commit 间隔。
六、关键配置说明 Fluss server.yaml(关键项)
coordinator.host: fluss-coordinator
zookeeper.address: zookeeper:2181
datalake.format: paimon
datalake.paimon.metastore: hive
datalake.paimon.metastore.uri: thrift://hive-metastore:9083
解释:datalake.format 指定归档目标为 Paimon,metastore.uri 指向 Hive Metastore。配置后,Fluss 会自动将历史数据写入 Paimon 表,并利用 HMS 管理元数据。
Flink flink-conf.yaml(关键项)
s3.endpoint: http://minio:9000
s3.access-key: admin
s3.secret-key: admin123456
execution.checkpointing.interval: 60s
解释:配置 S3 访问 MinIO,开启 Checkpoint 保证写入一致性。
七、常见问题排查
Q1:Fluss TabletServer 启动报错,连不上 Coordinator?
A:检查 COORDINATOR_HOST 环境变量是否正确设置,确保两个容器在同一 Docker 网络下,并且 Coordinator 容器名就是 fluss-coordinator。
Q2:Flink SQL 建表时提示找不到 Fluss Connector?
A:确认 fluss-flink-connector-0.6.0.jar 已放入 ./jars 并挂载进容器,重启 TaskManager 后生效。
Q3:MinIO 中没有看到数据文件?
A:Paimon 写入是异步的,检查 Flink 作业 Checkpoint 是否成功完成。也可以直接通过 Paimon 表查询,数据已经可见。
八、总结:下一步可以做什么?
至此,你已经在本地跑通了一套完整的湖流一体底座。这套环境可以:
作为实时数仓的沙盒,验证 Fluss 的主键表更新和部分列更新能力
接入 Flink CDC,模拟从 MySQL 实时同步到 Fluss,再自动归档 Paimon
部署 Trino,验证联合查询 Fluss + Paimon 的即席分析性能
后续我们也会基于这套底座,分享实时宽表拼接、Delta Join 优化、以及生产环境迁移的实战经验。
# 从 Hadoop 到湖流一体:数据底座的三次革命与终极选型指南
# 从分钟到秒级:我们用 Fluss + Paimon 替换掉 Kafka + Iceberg,实时宽表终于不用 Flink 死扛了