导语

BiFang 是腾讯大数据自主研发的湖流一体存储引擎,通过创新性地融合 Pulsar 流处理与 Iceberg 数据湖能力,实现流批数据处理入口统一,全面支持全增量数据查询、端到端数据实时可见等。BiFang 兼容主流的批流计算引擎,满足业务对数据实时性、一致性和灵活性的多样化需求。本文是 BiFang 技术系列文章之一,主要对数据存储以及读取做进一步的解析。

“BiFang,中文为毕方,中国古神话中的神鸟,象征着变革和能量,隐喻湖流一体存储引擎的先进和可靠。

01 背景

请在此添加图片描述

在传统架构中,消息队列(MQ) 与 数据湖(Lakehouse) 各司其职:

●MQ 系统(如天穹 Pulsar)提供高吞吐、低延迟的数据实时写入与消费能力,但缺乏表级别的元数据管理,数据通常以 Topic/Partition 的粒度存在,难以直接作为数据湖资产统一管理。

●数据湖系统(如天穹 Iceberg)提供强大的 Schema 演进、分区、快照、时间旅行等功能,适合长期存储和大规模分析,但在实时写入和秒级可见性方面存在天然不足。

请在此添加图片描述

BiFang 的设计目标就是打通这两个体系:

●写入端:将 MQ 的消息写入行为自然转化为表的写入操作;

●存储端:统一使用 Iceberg 元数据来管理流表、湖表、湖流一体表;

●查询端:既支持基于 Pulsar 的实时秒级消费,也支持基于 Iceberg 的批量分析。

这样,BiFang 能够实现从秒级数据可见性到长期数据治理的无缝衔接,满足企业级实时数据仓库的核心需求。

02数据存储模式

2.1. Apache Pulsar:实时流存储

●Ledger + Entry:每个 Topic Partition 的数据被顺序写入 BookKeeper Ledger,Ledger 内部由 Entry 组成,天然支持高并发和顺序消费。

●WAL(Write Ahead Log)特性:保证消息在落盘后才能对外可见,确保强一致性。

●扩展性:支持 Topic 分区扩展、Broker 和 BookKeeper 水平扩展,满足高并发写入。

2.2. Apache Iceberg:元数据与文件存储

●元数据分离:表的 Schema、分区、快照等均由 Manifest 与 Metadata File 管理。

●数据文件:底层以 Parquet/ORC 等列式文件持久化,优化分析性能。

●增量/全量能力:通过 Snapshot 支持 Time Travel 和增量消费。

2.3. BiFang存储抽象

请在此添加图片描述

●Table 和 Topic 一一对应。

●虚拟文件层:将 Pulsar Ledger + Entry 抽象为 Iceberg 可见的虚拟数据文件。

●在 Broker 层维护内存中的 Manifest 信息,定时合并并提交到 Iceberg Catalog。

●统一表接口:对用户而言,所有表(流表、湖表、湖流表)均通过 Iceberg Catalog 暴露。

这种分层保证了短期数据走 Pulsar,长期数据走 Iceberg,同时在表的语义上保持统一。

03实时写入和湖流元数据

3.1. BiFang 客户端写入

在传统 Pulsar 客户端中,写入只关心 Topic Partition;而在 BiFang 中,客户端需要增强,以便与 Iceberg 表的语义对齐。这样客户端写入行为从写 “MQ 消息” 提升为写 “Iceberg 表的分区数据”,流和湖在入口层面就统一。

请在此添加图片描述

3.1.1. 分区管理与路由策略

分区管理与路由策略通过精确分配消息至目标分区和灵活的 Topic Partition 路由,实现流式写入的高效聚合与负载均衡。

3.1.1.1. MQ 分区路由

为了保持与消息队列(MQ)并发写入模型一致,BiFang 在消息落入 Topic Partition 时提供三种路由模式:

●Round-Robin

按批次大小轮流切换 Topic Partition,实现负载均衡。

●Random

在固定批次大小内保持写入同一分区,达到阈值后随机切换,兼顾批次完整性与均衡性。

●KeyHash

○根据配置的 message-key 计算 Topic Partition,可选择 Java 原生哈希或 Murmur3 哈希算法。

○对于主键表:

 ■保证相同主键消息落在同一 Topic Partition,实现分区内一致性。

 ■Topic Partition 数量需与 Iceberg 表的 bucket 数量保持一致,以保证顺序性,为后续 bucket 级别去重提供保障。
3.1.1.2. 实时分区聚合

●基于表分区规则的消息归集:

根据 Iceberg 表定义的分区策略(例如 dt=2025-08-23、region=us),对每条消息进行目标分区的精确分配。

●实时写入中的分区优化:

在流式写入阶段即完成分区切分,从而保证相同分区的数据可以高效合并,有助于逻辑文件的组织与管理。这样不仅减少了后续查询时的复杂 Shuffle 操作,也提升了整体数据处理效率。

3.1.2. Schema 管理与兼容性

●扩展 Pulsar Schema Registry

在写入路径上增强 Schema 校验能力,确保消息格式与目标表 Schema 严格一致,从而保证下游在批处理和流式处理场景下能够实现统一、稳定的解析。

●支持 Schema 演进

在保证兼容性的前提下,支持字段的新增与删除,避免因 Schema 变化导致的作业中断或写入失败。

●统一 Schema 编码

在消息写入阶段直接完成 Schema 编码,采用 Avro 作为统一的数据序列化格式,实现跨引擎、跨场景的一致性处理。

3.1.3. 批消息容器(Batch Message Container)

请在此添加图片描述

●批消息容器机制

在客户端引入批消息容器(Batch Message Container),每个容器承载同一 Table Partition 的消息集合,实现分区内的高效聚合。

●容器与存储映射

每个容器直接映射为一个 BookKeeper Entry,在提升写入吞吐与效率的同时,与 Iceberg 的分区策略天然对齐,确保数据组织的一致性。

● 批次级元数据增强

在批次消息体中附加表级相关元信息,例如表分区标识(Table Partition)、水位线(Watermark)等,从而为下游的流批一体化计算与调度提供更精确的语义支持。

3.1.4. 事务和写入一致性保障

BiFang 支持 AT_LEAST_ONCE 和 EXACTLY_ONCE两种语义:

●AT_LEAST_ONCE

至少一次投递,保证不丢失但可能重复,核心原理是通过 flush + 等待确认机制确保消息至少被投递一次;

●EXACTLY_ONCE

精确一次投递,既不丢失也不重复,核心原理是基于 Pulsar 事务 + Flink 两阶段提交实现精确一次语义,依赖 flink checkpoint 并且对 Pulsar 集群稳定性要求较高,存在一定性能损耗。

3.1.5. 批量写入和指标统计

除了支持原生的单条写入模式,BiFang 还提供高效的批量发送模式。

● 批次级统计信息

自动计算每批数据的统计信息(如 Min/Max)并同步写入 Iceberg Manifest。

●利用元数据优化查询

Spark 等批处理引擎可利用 Manifest 中的统计信息进行高效过滤,减少无效数据扫描,显著提升查询性能。

3.2. BiFang Broker 写入

BiFang 对 Pulsar Broker 进行了深度改造增强,使其具备“实时存储 + 元数据管理”双重能力。

请在此添加图片描述

3.2.1. Manifest Store

BiFang 在写入路径中引入 Manifest Store 机制,用于实时记录写入操作的元信息,并保证与 Iceberg 的对齐和一致性。

3.2.1.1. WAL 与 Manifest Store 机制

●写入流程概览

每个写入请求首先持久化到 BookKeeper WAL,同时 Broker 生成一份 Manifest 元信息,包括 LedgerId、Entry 范围、分区信息和 Schema 信息,并写入到 Manifest Store,用于 Iceberg 后续的 delta 提交与对齐。

●Manifest Store 功能

○持久化存储能力

Table 数据写入 Bookie 后,按 <TopicPartition, TablePartition, LedgerID, EntryID> 组织 delta manifest 信息,并持久化到 Manifest Store。

○读取服务

Manifest Service 从 Manifest Store 读取 delta manifest,处理并提交到 Iceberg,提交成功后通知 Manifest Store 更新读取进度。

○一致性保障

数据与 delta manifest 写入并非原子操作,因此需要额外机制保证两者一致性。

●Manifest Store 实现

基于上述需求,BiFang 选择使用 Pulsar 内部 Topic 来实现 Manifest Store。

3.2.1.2. Manifest Topic 创建与命名

●创建策略

Manifest Store Topic 与 Table Data Topic 一一对应,在创建 BiFang Table 时,系统自动创建表对应的 Table Topic 与 Manifest Store Topic,分区保持一致。

●命名规范

ManifestStoreTopic=<table topic>+"_BiFang_MANIFEST_STORE"

●示例

○Table Topic:

persistent://tenant/namespace/table-test

○ Manifest Store Topic:

persistent://tenant/namespace/table-test_BiFang_MANIFEST_STORE

3.2.1.3. Manifest Store 数据读写流程

●写入流程

  1. 数据写入 BookKeeper,获得 ledgerId 和 entry 信息

  2. 从 entry metadata 获取 Topic Partition / Table Partition 信息

  3. 将 <TopicPartition, TablePartition, LedgerID, EntryID> 写入 Manifest Store Topic

  4. 返回写入响应给客户端

● 读取流程

Manifest Service 发起读取,通过持久化订阅方式获取数据,订阅名约定为 "__BIFANG_MANIFEST"。

3.2.1.4. 数据一致性保障

● 非事务场景

可能出现 Table Topic 数据写入成功,但 Manifest Store 数据未写入的情况,由于客户端会重试写入,此时流式读取可能出现重复数据,但批处理读取数据保持一致。

● 事务场景

Table Topic 与 Manifest Store 写入同属一个事务,提供强一致性保证,避免重复或丢失

3.2.2. Manifest Service

Manifest Service 是 BiFang 的核心模块,作为 Pulsar 流数据与 Iceberg 元数据之间的桥梁,实现增量数据处理、文件组织、快照提交及实时查询等关键功能。

3.2.2.1. 流式增量数据处理与逻辑文件组织

将 Pulsar 流式增量数据(Delta Manifest)按规则组织为逻辑文件,为后续批量提交至 Iceberg 做准备,从而解决小文件问题并提升管理效率。

●数据组织规则

○目录结构:按表和分区划分独立目录,例如 mytable_p0/(表示 mytable 表的第 0 个分区)。

○文件命名格式:[partition_index]-[ledger-id]-[schema_version]_[entry-range].log

■partition_index:分区编号 ■ledger-id:Pulsar 消息 Ledger 编号 ■schema_version:数据 Schema 版本 ■entry-range:Entry 编号的起止范围,例如 0-99

● 处理流程

  1. 从 Pulsar 流中持续消费增量数据,每条记录包含 ledgerId、entryId、表分区等元信息。

  2. 按表分区、Ledger、Schema 版本等维度分组数据,并暂存在 Manifest Cache 中。

  3. 当触发合并条件(累计数据量超过 128MB 或定期触发)时,将分组数据合并为逻辑文件,文件名记录 Entry 起止范围。

  4. 生成的逻辑文件即 Iceberg 的 DataFile,记录数据量、文件大小、分区、LedgerId、Entry 范围等元信息。

3.2.2.2. Commit 到 Iceberg

将缓存的增量数据批量落盘,生成 Iceberg 快照,保证数据一致性与持久化,并记录消费进度。

●触发方式

○定时自动触发:服务启动后按配置时间间隔(如 10 秒)自动检查新数据并提交。

●处理流程

  1. 整理 Manifest Cache 中数据,识别待提交的新数据。

  2. 暂存当前消费进度(消息 ID)与待提交数据,准备生成 Iceberg 快照。

  3. 调用 Iceberg 接口,将数据写入表并生成新快照,同时将消费进度记录到快照元数据。

  4. 提交成功后,清理缓存数据。

  5. 向 Manifest Store 发送 ACK,确认消息已处理完成。

3.2.2.3. 实时 Manifest 查询服务

请在此添加图片描述

提供最新 Manifest 文件查询能力,包括尚未 Commit 到 Iceberg 但已在 Pulsar 持久化的数据,支持实时分析与数据校验。

处理流程:

  1. 聚合并缓存消费到的增量数据(含未提交数据)。

  2. 接收“查询最新 Manifest”请求时,将缓存中未提交的 DataFile 与已准备好的快照动态合并,生成增量的“实时 Manifest 文件”。

  3. 实时 Manifest 与全量 Iceberg Manifest 格式一致,反映当前所有增量变更。

04 总结

BiFang 通过对 Pulsar 客户端、Broker 的改造,打通了实时流写入与数据湖管理的通道,实现了从秒级可见性到长期数据治理的一体化。相比单独的 MQ 或 Lakehouse 方案,BiFang 在以下方面具有独特优势:

●面向表语义的实时写入;

●流与湖统一的元数据管理;

●秒级可见的实时/离线链路。

未来 BiFang 将持续从架构优化、核心能力增强与生态体系扩展等多个维度进行演进:

●在架构层面,持续优化流湖一体化的元数据与存储体系,以提升系统的可扩展性与稳定性;

●在核心能力方面,将进一步强化实时数据写入、统一元数据管理以及跨引擎访问能力;

●在生态层面,将与 Oceanus、InLong、WeData 等数据产品形成更紧密的集成,同时深度结合 Apache Iceberg,探索多样化的 AI 数据管道场景。

文章来源于腾讯云开发者社区,点击查看原文