摘要:导读Iceberg 是一种分布式数据湖表格式,聚焦于大规模数据集的高效管理与查询。其优势包括支持行级更新、具备事务及快照功能,并且能实现高效的数据查询,在众多互联网企业中得到了广泛应用。本文将介绍 Iceberg 在华为终端云的实践。
导读Iceberg 是一种分布式数据湖表格式,聚焦于大规模数据集的高效管理与查询。其优势包括支持行级更新、具备事务及快照功能,并且能实现高效的数据查询,在众多互联网企业中得到了广泛应用。本文将介绍 Iceberg 在华为终端云的实践。
文章将围绕下面三点展开:
1. 终端业务简介
2. Iceberg 在华为终端云的使用实践
3. 未来规划以及展望
分享嘉宾|李立伟 华为 软件工程师
编辑整理|李笑宇
内容校对|李瑶
出品社区|DataFun
01
终端业务简介
华为终端云以全场景智慧体验以及 “1+8+N” 生态为核心,通过持续的技术创新与平台升级,连接更多优质服务和高品质内容,致力于为全球消费者提供安心、智慧、便捷、丰富且个性化的全场景数字生活体验。
华为 HarmonyOS 能让手机、平板、智能手表等多种终端设备实现硬件互助、资源共享,打造超级终端。HarmonyOS NEXT 即鸿蒙 5.0,已开启多机型公测,欢迎大家试用。
02
Iceberg 在华为终端云的使用实践
接下来,将深入探讨 Iceberg 在华为终端云不同场景中的应用实践。
1. 特征设计与挖掘
特征工程是数据分析与应用开发的关键环节,在这一环节中,华为终端云曾面临一系列棘手的痛点。
面对这些痛点,#华为终端云 借助 Iceberg,采取了一系列有效的解决措施。
首先,利用 Iceberg 建立了如上图所示的离线特征加工范式。指标加工统一管理,以保证口径一致。每个主键一个特征表,解决特征重复建设的问题。统计类特征通过对数组求和实现,不必对长周期历史数据进行统计。
传统的 Hive 数仓在数据更新操作方面支持不足,主流操作 Insert overwrite 存在诸多弊端,如记录数据变动时需重跑整个历史分区或使用拉链表,不仅浪费数据资源,时效性也较差,下游任务严重依赖上游任务的完成情况,容错度低。而 Iceberg 的行级更新能力是其核心优势之一,通过 Merge Into 操作,业务逻辑更易理解,#数据架构 更加统一,性能也有显著提升,同时还能部分解耦上下游任务,通过更细化的事务冲突解决方案,降低了对上游任务的强依赖。
不过,Merge Into 也存在一些不足。在实时场景下,更新频率越高对业务价值越大,例如分钟级的推荐刷新相比天级刷新能显著提升 GMV,但 Flink 的流处理模型并不适用于 Merge Into 场景。此外,Iceberg 的文件快照管理方式在频繁提交时会产生大量小文件,增加了后期管理成本。
基于多方面的原因,我们引入基于 LSM(Log-Structured Merge-Tree)的文件列更新方式。
LSM 架构的思想之一是利用磁盘顺序写的高效性来提升性能。数据首先写入内存中的 MemTable。当 MemTable 达到一定大小,会变为只读的 Immutable MemTable,并开始写入新的 MemTable。Immutable MemTable 会被刷写到磁盘,形成 Sorted String Table(SSTable)文件,文件内部数据有序,便于后续查找和合并。随着 SSTable 文件增多,系统会定期合并和压缩这些文件,删除重复和过期数据,减少文件数量和查找开销。
此时,当多个流对同一张表的不同列进行写入时,只要主键相同,那么在合并进行时,这些列就会合并到一个文件里面。同时,为了平衡读写性能,用户可以选择不同的合并策略,比如写入时不合并文件,从而让写入性能得到最大化的提升。
业务在对特征进行训练或者探索的时候,表结构变化是非常频繁的。为了将表的 Schema 变更对任务流的影响最小化,设计了 JSON/MAP 数据自动映射,通过事件监听的方式,实现了表结构变更的端到端一致性。
具体实现为,通过 Flink 流监听 Schema 的动态变化,当表的 Schema 发生变更时,会触发变更事件,处理结构变更的算子接受到变更事件后,将变更广播到所有序列化-反序列化数据流的算子内部,此时会将旧数据刷写到磁盘,并将 JSON/MAP 中的数据按照新的 Schema 进行解析,取出对应的新字段。
以 JSON 流新增字段为例:
初始状态:表结构为{id: int, name: string},Flink 流持续写入 JSON 数据。变更触发:上下游新增字段 age: int,触发新增字段事件。协调处理:Flink 暂停处理数据,Sink 端将内存中{id, name}数据刷盘。后续处理:新到达的 JSON 按新 Schema 解析后写入文件,正常提交快照。ABtest 场景中,用户通常会在 Iceberg 表上创建分支,写入实验组数据,然而,实验分支数据可能和主干分支数据仅仅是新增字段的差异(此处已支持了 Branch 绑定特定的 Schema,即主分支与实验分支的 Schema 可以不同),那么这时候也会有两个流,一个流写入主干分支,一个流写入实验分支,除了新增字段外,其它字段都被重复写入了两份,考虑到此类表往往字段非常多,这在存储及效率是都是较大的浪费。
所以,物理上将 Branch 与 Schema 相绑定,虽然实现简单,但并不算最优解。
为了解决问题,结合 LSM 树,我们设计了 Schema Version 机制。Schema Version 相当于一个虚拟 Schema+Branch,实现了分支和 Schema 的虚拟映射,最终的表 Schema 将是所有分支的并集。
当一个流写入表时,不同的 Branch 将不再是物理上切分了表,而只是取了表的不同 Schema 子集,它有些类似视图,但又与视图不同,视图并不涉及最低层文件组织形式,但这里的变化会影响到表如何组织数据,在使用上更接近物化视图的概念。
LSM 的合并方式采用分级合并,在从 L0 往 Ln+1 层合并的过程中,通过元数据版本控制,可以控制分支字段仅在特定层有效,在该层级以下,分支字段不再往下合并。比如主干 Schema Version=1 有字段 A、B、C,分支 Schema Version=2 添加字段 D(或删除字段),合并时,字段 D 停留在 L2 层,避免向下合并,需要删除字段 D 时,只需清理 L2 层 Schema Version=2 的文件。
2. 基于水位线的延迟数据处理及部分 WAP
在流式数据处理中,时效不同的数据价值也是不同的,时效越高的数据价值越高,基于此,将高时效性数据(新到达的数据)和低时效性数据(迟到或历史数据)分开处理,当低时效数据到达时,将数据进行累积,累积到一定规模后再合并计算,减少计算开销。
索引包括三部分:基于最新快照的主键索引,基于最新 Manifest 的统计索引,以及所有文件的多级索引。
基于最新快照的主键索引:通过主键快速定位到最新快照中的数据文件,通常用于点查场景,比如根据主键快速找到对应的行。基于最新 Manifest 的统计索引:Manifest 文件记录了数据文件的元信息,如路径、分区信息、统计信息(如每列的最小值、最大值等)。统计索引可能利用这些统计信息来过滤无关的数据文件,加速查询。所有文件的多级索引:针对文件而非数据构建索引。Flink 流写 Iceberg 的过程整体分为三个部分,分别是数据写入准备 Sink Write,事务提交 Commit,提交后处理 Post-Commit。Commit 和 Post-Commit 阶段的区别在于 Commit 仅处理元数据更新(轻量级),Post-Commit 阶段处理数据重排(重量级等)。
Post-Commit 阶段核心操作为索引生成,文件合并,数据生命周期管理等。索引生成是为了加速后续查询;文件合并是将小文件合并成大文件,优化读取性能;数据生命周期管理可以自动清理过期快照、删除孤立文件;通过引入 Post-Commit 阶段,在保证事务原子性的同时,实现了:
查询加速:通过异步生成索引、合并文件提升读取效率。扩展能力:支持自定义数据管理策略(如生命周期规则)。3. 实时化
在写入时,数据会同时写入持久化文件和消息队列,并在提交给 Iceberg 的元数据中记录消息队列信息,以保证数据完整性。
在读取时,最终实现了三种读取方式:
批模式:读取完整的文件快照,适用于离线分析、历史数据回溯。流模式:读取 LogStore 中的增量数据,支持低至秒级的延迟,用于实时监控、事件驱动型应用。混合模式:结合文件快照+增量日志(如初始化状态从文件加载,后续增量通过流消费)。03
未来规划展望
1. 从 Table Format 向全生命周期演进
这张图清晰展示了 Apache Iceberg 作为数据湖表格式的扩展能力,其核心围绕三个规则引擎展开(服务/运维/安全)。
服务规则引擎(功能增强层)生命周期处理:比如自动化管理表分区/快照的保留策略。数据重分布:比如动态优化数据文件布局(如 Z-Order)。仓库压实:比如智能合并小文件(基于规则自动触发)。缓存机制:比如元数据缓存加速查询,支持 TTL 失效策略。运维规则引擎(可观测层)实时质量校验:比如通过预置规则库进行约束检查(如空值率监控)。质量指标报告:比如自动化生成 SLA 合规报告。低效任务检测:比如识别元数据处理周期较长、多流写入产生事务冲突过多的表任务。该架构表明 Iceberg 正在从单纯的表格式向可视化全生命周期管理平台演进,通过规则引擎体系实现"配置即策略"的声明式数据治理能力。
2. Catalog 增强
在传统的数据处理流程里面,引擎将直接访问 HMS(Hive Metastore)并读取存储在对象存储或 HDFS 上的元数据文件,当集群规模较大,或表元数据文件过多时,任务将花费更多的时间在 Plan 阶段,甚至出现假死。优化之处体现在:
REST Catalog 将 HMS 进行封装,Runtime 将直接访问 REST Catalog,解耦了 HMS,后端可以进行切换,且不再强依赖元数据文件。通过缓存设计,减少访问 HMS 和文件元数据的开销,且多个任务之间可以直接访问共享的内存 Cache。兼容社区索引基于 LSM 的数据预聚合:改变数据合并的方式,以往是对相同主键的不同数据进行简单合并,后续希望在写入时可以根据自定义算法进行预聚合。来源:DataFunTalk