Apache Fluss破解大数据最后一公里难题


Apache Fluss是阿里与Ververica为Flink打造的实时表存储引擎,通过分层存储和高效changelog机制弥补了Paimon的不足,支持低延迟数据读写与湖仓统一访问。尽管尚未支持Schema演进,但其设计理念与扩展潜力为流处理存储层提供了新思路。

作者Jack Vanlightly是Confluent的数据系统专家,以深度技术解析闻名。他曾详细剖析过Apache Kafka、BookKeeper及Iceberg等数据框架的底层架构,这次他将目光投向了阿里巴巴与Ververica联合开发的Apache Fluss——一个专为Flink打造的实时表存储引擎。



一、为什么Flink需要Fluss?

虽然Apache Paimon(原Flink Table Store)已经为Flink提供了表存储支持,但在处理实时数据时,其延迟和成本仍然较高。尤其在处理 changelog(变更日志)时,Paimon需要依赖查找或全量压缩,效率较低。而Fluss的出现,正是为了弥补这一缺口。

Fluss被设计成一个 disaggregated(解耦式)的存储引擎,既可作为Flink的低延迟表存储层,也能将数据下沉到Paimon等数据湖中,实现实时与历史数据的无缝衔接。



二、Fluss的核心架构:不只是又一个Kafka克隆

Fluss由三部分组成:Tablet Server(数据片服务器)、Coordinator(协调器)和Client(客户端)。其中,Tablet Server负责实时数据存储,Coordinator类似Kafka的Controller,负责元数据和协调任务,而Client则嵌入Flink中,提供读写接口和跨层数据合并能力。

Fluss支持两种表类型:
- Log表:仅追加写入,类似Kafka主题,但支持列式存储(Apache Arrow格式)和投影下推(projection pushdown),查询时只需读取所需列,节省网络和计算资源。
- 主键表:支持增删改查,每个变更都会生成changelog,底层通过RocksDB存储状态,并通过子Log表保证持久性。

值得注意的是,Fluss的Log表复制机制基于Kafka的副本协议,但在分片设计上做了重大改进:数据先按分区列(如日期、国家)做分区,再分桶(bucket),每个桶对应一个物理Log Tablet,类似Kafka的分区,但更贴合表模型。



三、如何实现低延迟与高效changelog?

Fluss的主键表通过RocksDB实现高效点查和前缀查询,changelog则通过追加写入Log表产生。写入时,Fluss会先计算变更类型(插入/更新/删除),再写入Log表,最后更新RocksDB。这种设计避免了Paimon在生成changelog时的查找开销,也更节省内存。

此外,Fluss支持部分更新和多种合并策略(如FIRST_ROW保留首条记录,VERSIONED按版本保留最新),适合流式场景下的数据更新。



四、分层存储:实时层与数据湖的统一

Fluss支持两种分层存储:
- 内部分层:类似Kafka的Tiered Storage,将旧数据段(segment)上传到对象存储,但由客户端直接下载,减轻服务器压力。
- 数据湖分层:通过Flink作业将数据从Fluss写入Paimon或Iceberg,由Coordinator协调偏移量提交,确保数据不重不丢。

客户端在读取时,会自动合并实时数据(来自Fluss集群)和历史数据(来自Paimon),对用户完全透明。这种设计使得Fluss更像一个分布式缓存层,而Paimon作为冷存储,两者共同构成统一的主存储。



五、挑战与未来

Fluss仍面临一些挑战:
- 尚未支持Schema演进,限制了生产环境适用性;
- 生命周期管理目前仅基于TTL,未与数据湖分层联动;
- 副本机制依赖网络传输,在云环境下可能成本较高。

但Fluss的路线图中已经包含直写对象存储、多引擎(如Spark)支持和Iceberg集成等计划。未来,它可能不仅服务于Flink,更成为通用实时数据湖加速层。



六、对Kafka社区的启示

Fluss在Kafka副本机制之上,增加了表结构、列式存储和投影下推等特性。这或许值得Kafka社区思考:是否可以在保持灵活性的同时,通过Schema化和列式优化提升分析效率?