开源流式湖仓服务 Arctic 详解:并非另一套 Table Format
本文根据作者于 Arctic 开源发布会演讲内容整理(略有删减),系统解读 Arctic 项目研发初衷、生态定位、核心特性、性能表现及未来规划。
首先感谢大家参与我们 Arctic 开源发布会。我是马进,网易数帆实时计算和湖仓一体团队负责人。我们在 2020 年开始关注数据湖新的技术,并用它来构建流批一体、湖仓一体的架构。最早我们使用 Flink+Iceberg,但是实践过程中发现这个架构距离生产场景还有很大的 gap,所以有了 Arctic 项目(GitHub - NetEase/arctic: Arctic is a streaming lake warehouse service open sourced by NetEase)。
![](https://pic4.zhimg.com/80/v2-ba8c699178b58a140da8b95755a72bef_720w.jpg)
数据湖 Table format 之争
先看目前 Apache Hudi、Apache Iceberg、Delta 这几个主流的开源 Table format(表格式)的选型。
Table format 这个概念最早由 Iceberg 提出,现在行业对它的理解主要有两点。第一点是 Table format 定义了哪些文件可以构成一张表,这样 Apache Flink、Apache Spark、Trino、Apache Impala 等任何引擎都可以根据 Table format 去查询、检索数据。第二点就是 Table format 规范了数据和文件的分布方式,任何引擎写入数据都要遵照这个标准,通过 format 定义的标准来支持以前 Hive 不支持的 ACID 和模式演进。我们看到 Iceberg、Delta 和 Hudi 在这些功能上基本上是拉平的,虽然他们在各自实现上有很大不同,但抽象他们的共性个人认为是非常有意义的事情。
![](https://pic2.zhimg.com/80/v2-907c39884844aca8e4d9fdeb38f417a1_720w.jpg)
拿目前主流的数据湖 Table format 和 Hive 进行对比,Hive 简单定义了表和 HDFS 上静态目录的映射关系,它本身是没有 ACID 的保障的,我们在真实的生产场景中只能单读单写。目前我们上层的数据中台或者是 DataOps 平台能够通过工作流的方式保障我们能正确使用 Hive,当然只能用于离线场景。
![](https://pic1.zhimg.com/80/v2-0c3aa996993c6a72644da204bcfb5aa0_720w.jpg)
新的 Iceberg、Delta、Hudi 所主导的 Table format 能力中,增加了一个快照的概念,表的元数据不再是一个简单的表和文件的关系,变成了表和快照以及快照和文件的关系,数据的每次写入会产生新的快照,而这个快照和文件产生一个动态的映射关系,这样它能实现每次写入 ACID 的保障,也能通过快照的隔离实现用户的多读多写。而且基于快照也能给上层提供一些比较有意思的功能,比如说可以基于快照的增量写入实现增量读,也就是 CDC 的功能,可以通过快照去支持回溯,例如我们在 time travel 或者数据的 rollback。
总结下来 Table format 有四点核心特性。
第一,结构自由。像之前的 Hive 只能支持简单的加列操作,而在 Delta、Iceberg 这样的 Table format 之上用户可以自由地更改表的结构,可以加列、减列、改列,而且对数据的迁移和变更不会有要求。
第二,读写自由。因为它通过快照能够保证数据的 ACID,任何实时、离线以及 AI 的需求都可以自由地往这个表里面写数据或者读数据。
第三,流批同源。因为 Table format 核心的一个功能是可以很好地支持流场景,我们的批和流都可以往新的 Table format 去写和读。
第四,引擎平权。这点非常重要,它不能只是绑定某一个引擎,比如说像 Delta 在 1.0 时代是 Spark 生态中的一个组件,在一个月之前 Delta2.0 的发布再次向我们证明了去适配多个引擎的重要性。
在 Table format 这些项目的官网中,他们会主推一些功能主要包含 CDC、SQL 扩展,数据的 Rollback,以及 time travel,模式演进(Schema evolution)以及我们经常说的流式更新(Upsert)、读时合并(merge-on-read)的功能。
CDC 一定程度上能起到平替消息队列的作用,比如说在生产场景中,实时计算主要会用 Kafka 或者 Pulsar 做流表的选型。有了 Table format 之后,我们可以基于数据湖来实现类似于消息队列的功能,当然它的数据延迟会从毫秒或者秒级降级为分钟级别。像 Upsert、读时合并和行业内或者说很多公司去推广数据湖的主要场景,就是拿这个实时更新以及读时合并去平替 Apache Kudu、Doris、Greenplum 这些实时更新的数仓系统。
企业需要怎样的数据湖
首先一点是如果我们只是关注数据湖 Table format 中个别的功能,推广起来是非常困难的。比如说数据湖的 CDC 功能,确实在某种程度上能够平替消息队列,但是也会引入一些其他的问题:首先是延迟的问题;其次是用数据湖做消息队列可能会引入很多小文件,这个小文件谁来管理?还有第三个是比较隐形的问题,以前消息队列的成本就是挂在业务团队那边,如果我们现在用一个公共的数据湖底座,这个成本该怎么分摊?
在过去两年中,我们跟行业内很多公司交流,大体上都是在这样一种矛盾之中挣扎,想用数据湖的新技术来替代一些其他方案,对业务的吸引力是非常不足的。我们的数据湖或者 Lakehouse(湖仓一体)的技术究竟能给企业带来怎样的价值?
在我们的生产场景中,我们的整个数据平台体系在 2020 年遇到最主要的问题,就是流批平台割裂。大家知道我们围绕 Hive 这套离线数仓已经产生了非常丰富的方法论,从数据模型、数据资产到数据质量,基于数据湖的开放架构我们产生了非常好的一套规范、标准以及治理体系。
但是我们把目光切换到实时场景下,目前主要用 Flink 做实时计算,用 Kafka 作为流表的选型,当我们做流表 join 时可能单独需要从数据库那边拉一个实时同步的任务,后面如果我们做数据分析,需要比较高的数据新鲜度,需要引入 Kudu 或者 Doris 这些能够准实时或者实时更新的数仓系统。
这套东西和我们离线整套的技术选型以及工具是非常割裂的,而且没有形成比较好的规范,主要还是点对点的开发为主。
举个例子,如果我们既要做实时也要做离线,就需要拉两套链路。离线的链路根据我们整套方法论,根据离线整个流程的工作流,是能比较容易规范地定义出一套出来。实时场景下我们更多需要开发者,需要用户自己去了解 Flink 怎么玩儿,Kafka 怎么读,这个过程中序列化、反序列化怎么做,怎么在 Kudu 上建表,这一套规范给用户带来了非常大的负担。
![](https://pic3.zhimg.com/80/v2-cbd8790538881aa541cee3f9ff5598ea_720w.jpg)
尤其是 AI 的一些业务,他们要做数据生产,其实更加关注数据训练、样本这些跟 AI 相关的流程本身,对 HBase、KV 这些他们是一概不了解的,所以他们会把需求提到另外一个团队,而另外一个团队只能点对点地去响应。
总结一下传统 Lambda 架构给我们带来哪些弊端。
第一是数据孤岛的问题。如果我们使用 Kudu 或者其他跟数据湖割裂的一套数仓方案,会带来独立的采购和部署成本,会因为容易存储而浪费成本。因为数据之间难以复用和互通,如果我们在相同的业务场景下需要一个实时的数仓,可能需要从源头重新拉一份数据出来,导致成本和人效的浪费。
第二是研发人效低,研发体系割裂,研发规范不通用。这在 AI 特征、推荐的场景比较典型,需要用户自己去搞定什么时候调用实时的东西,什么时候调用离线的东西,会导致整个业务层非常复杂。
最后是指标和语义的二义性问题。比如过去几年我们主要是使用 Kudu 作为实时数仓方案,用户需要自己在 Kudu 里面建一个数仓表,会有 Kudu 的一套 Schema,在 Hive 这边有一套通过数据模型创建的表,而这两套东西都需要用户自己去维护。当业务逻辑发生变更的时候,用户可能改了 Hive 但是没有改 Kudu 的,长久下来就会导致指标和语义的二义性问题。而且随着时间的推移,维护的成本会越来越高。
所以业务期望的是什么呢?其实是我们在平台层,在整个数据中台层或者在整套数据的方法论这一层,能够用一套规范、一套流程把实时和离线,以及 AI 等更多的场景统一。所以我们回过头来看 Lakehouse 这个概念创造出来的意义,就是拓展产品的边界,让数据湖能更多地服务于流的场景、AI 的场景。
在我们的生产场景中,Lakehouse 给业务最终带来的应当也是一个体系上的收益,而不在于说某一个功能上用了它。比如说我在 CDC 或者在分析的场景下用了,但是如果用户只是单纯地去比较 Kudu 和 Hudi 或者 Iceberg 之间的差异,他可能很难说到底带来什么样的收益;但是如果我们告诉用户说整套平台可以即插即用地把离线和实时全部统一掉,这个收益就很大了。基于这样一个目标,我们开发了流式湖仓服务 Arctic 这样一套系统。
理解 Arctic 流式湖仓服务
Arctic 是什么呢?简单来说 Arctic 是由网易数帆开源的流式湖仓系统(Streaming LakeHouse Service),它在 lceberg 和 Hive 之上增加了更多实时场景的能力,所以 Arctic 首先强调的是实时场景的能力,并且面向 DataOps 提供开箱即用的元数据服务,而且让数据湖更加好用和实用。我们用一句话概括会比较抽象,后面我们会用更多功能的举例以及我们一些干货上的分享,让大家深入理解 Arctic 到底是什么。
生态位差异
首先我们通过这张图强调生态位的差异,Arctic 从生态位上在 Table format 之上,所以严格意义上说我们不应该把 Arctic 当成是另外一套 Iceberg 或者另外一套 Table format。
![](https://pic4.zhimg.com/80/v2-6b09cc90ecc954b69f798eb158f42f0f_720w.jpg)
另外一点,我们在 Table format 之上,主要考虑跟开源的 Table format 做兼容,所以 Arctic 的一个核心目标是帮助企业用好数据湖的 Table format,以及解决或者拉平在 Table format 以及用户,或者说产品真实的需求之间的 gap。
Arctic 本身包含两个核心组件,第一个是元数据服务 AMS,它在我们系统中定位是下一代 HMS 的角色。第二个,我们持续自优化的功能,会有整套 optimizer 组件和机制,来实现后台数据优化。
Tablestore 设计与优势
我们之前和很多用户聊过 Arctic,大部分用户的第一个问题是我们跟开源的 Iceberg 具体是什么关系。通过这张图我想来说明这点。首先在 Arctic 中有 Tablestore 这个概念,Tablestore 是一个存储单元的定位,有点类似于传统数据库里面聚簇索引的概念。当流式写入的时候,我们会用一个 change 的 Tablestore 存储一个 CDC 写入的数据,这个数据有点类似于我们数据库中的 binlog 或者 relog,后面这个 change table 可以用于 CDC 的回放,也可以当作一个单独的表来访问。
![](https://pic4.zhimg.com/80/v2-36609e2a519639c7dbf1df251f30c27b_720w.jpg)
Hudi、Iceberg 也有 upsert 的功能,但 2020 年我们开始做这个事情的时候 Iceberg 还没有这个功能,社区出于对 manifest 这层设计的严谨考量在实现上会有一些妥协,所以最终我们决定了在上层去做这个事,并且会体现我们的一些优势。
Change 表主要存储的是 CDC 的 change 数据,另外还有一套 Basestore 会存储我们的存量数据,两个 Tablestore 其实是两张独立的 Iceberg 表。另外我们还可选的集成 Kafka 的 logstore,也就是说我们的数据可以双写,一部分先写到 Kafka 里面,再写进数据湖里,这样实现了流表和批表的统一。
这样设计有什么样的优势?首先 change 表里的 CDC 数据可以按顺序回放,会解决 Iceberg 原生的 V2 CDC 不太好回放的问题。
第二个是 change 表可以开放访问。在很多电商、物流的场景里 change 数据不光是作为一个表内置的数据用,很多时候订单表、物流表的变更数据也会作为独立的数仓表来用,我们通过这样的设计允许把 change 表单独拎出来用,当然会添加一些写入保护。如果未来业务有一些定制化需求,比如说在 change 表中额外添加一些字段,添加一些业务自己的 UDF 的计算逻辑,这个设计也具备这样的可能。
第三点我们这套设计理念 change 和 base 之间的转化,这个过程是 optimize。这个概念在 Delta、Iceberg 和 Hudi 中都有介绍过,它的核心是做一些小文件合并,我们把 change 数据到 base 数据的转换也纳入 optimize 的范畴,并且这些过程对用户来说是透明的,如果用户直接用 Iceberg 或者 Delta,所有的 optimize 操作在底层都会有一个快照,这样对用户是不友好的,我们在上层把这套东西封装起来了。当用户读一个高新鲜度的数据做分析时,我们的引擎端会做一个 change 和 base 的 merge-on-read。
Arctic 架构和组件
理解了 Tablestore 的概念之后再来看 Arctic 的架构和组件,我们就会更加容易理解。在数据湖这一层我们有 change files、base files,分别对应 changestore 和 basestore。Tablestore 的概念不仅可以用于 CDC 的场景,未来对于一些排序,对于 ZOrder 一些具体的需求同样可以采用上层架设独立的 Tablestore 来解决。
![](https://pic4.zhimg.com/80/v2-6c8197e67118abca787e8799b6841cc3_720w.jpg)
在上层我们有一个前面介绍过的 AMS(Arctic Meta Service),AMS 是 Arctic 流式湖仓服务中 “服务” 这一层所重点强调的组件,是面向三元组的元数据中心。
三元组是什么呢?就是 catalog.table.db 这样的三元组,大家知道在 Spark 3.0 和 Flink 1.2 之后,主推的是 multi catalog 这样的功能,它可以适配不同的数据源。目前我们在主流的大数据实践中更多的是把 HMS 当作元数据中心来使用,HMS 是二元组的结构,如果我们想扩展,把 HMS 里面根据更多的数据源,需要做很多定制性的工作。比如说网易数帆有数平台其实是在 HMS 之外单独做了一个元数据中心,来管理三元组和数据源的关系,AMS 本身就是面向三元组设计的元数据服务。
第二个我们的 AMS 可以和 HMS 做同步,就是我们的 Schema 可以存在 HMS 里面,除了 Hive 所能够存储的一些字段信息外,一些额外的组件信息,一些额外的 properties 会存在 AMS 中,这样 AMS 可以和 HMS 一起提供服务,所以业务不用担心在使用 Arctic 的时候一定要做一个替换,这其实是一个很灰度的过程。
第三个是 AMS 会提供事务和冲突解决的 API。
在 optimizer 这儿,我们有一整套完整的扩展机制和管理机制。首先我们有一个 optimizer container 的概念,本质上是平台调度任务的组件,我们整个后台的 optimize 过程对业务来说是透明的,后台需要有一套调度服务,能够把 optimize 的进程调度到一个平台中(比如 YARN 上、K8s),这种不同的模式就是 optimizer container 的概念,未来用户也可以通过 container 接口去扩展它的调度框架。
optimizer group 是在 container 内部做资源隔离,比如说用户觉得有一些表的 optimize 需要高优先级运行,可以给他抽出一个独立的 optimizer group 执行他的优化任务。
第三点在我们架构中有单独的 Dashboard,也是我们的一个管理界面,我们非常注重湖仓本身的管理体验。
最后一点也是非常重要的,刚才提过我们有 Table format 完全兼容的特性。目前提供两种,一个是 Iceberg,因为我们是基于 Iceberg 来做的,basestore、changestore 都是独立的 Iceberg 表,并且我们的兼容是随着 Iceberg 的迭代持续推进的,目前已经兼容 Iceberg V2。
另外我们也有 Hive 兼容的模式,能让业务在不用改代码的前提下,直接使用 Arctic 的一些主要功能,如果用户使用的是 Hive format 兼容,它的 change 数据还是存在 Iceberg 里面的。
管理功能
之前有提到 Arctic 非常注重管理体验,尤其对于我们后台持续优化的管理,有一套功能以及相对应的度量和标定的能力提供给大家。下图中所展现的,哪些表正在 optimizing 用到的资源、持续的时间,未来应该怎样做一个更合理的资源调度,通过我们的管理功能都会给到大家。
![](https://pic4.zhimg.com/80/v2-44746d92683343e31cdea96126bc07c3_720w.jpg)
我们的 table service 的功能,对于表有很多元数据的信息,包括每张表动态的变更,一些 DDL 的历史信息,事务的信息,都会在表服务中体现。
![](https://pic3.zhimg.com/80/v2-4aaae6a60498542700b07c3ef39b3ee2_720w.jpg)
并发冲突解决
当我们采用了 Table format 去解决流批同源场景的时候,举个例子,比如下图上半部分,我们在做一个数据的 CDC 同步,正常情况下是一个 Flink 任务去做持续的同步,但是如果我们想做数据回滚或者要做数据更正,比如说添加了一列,这一列有个默认值,需要我们通过批的方式把数值初始化一下,会起一个 Spark 任务和 Flink 同步去跑。这个时候如果 Saprk 任务和 Flink 任务操作到了同一行数据,这个数据的主键是一样的,就会遇到数据冲突的问题。
![](https://pic3.zhimg.com/80/v2-20f4c629e0522593b8bb258aff61b26a_720w.jpg)
现在在 Table format 这一层普遍提供的是乐观并发控制的语义,当我们出现冲突的时候首先想到的是让某一个提交失败,换句话说,乐观并发控制的语义核心的一点是不允许并发出现,那么在我们这个场景里 Spark 任务可能永远提交不成功的,因为我们对它的期待是做全部的数据重写,这样它的数据范畴是一定会和我们的实时数据冲突的。但业务肯定希望他的数据能够提交成功,所以我们提供了并发冲突解决的机制,让这个数据能够提交成功,并且同时保障它依然具有事务一致性的语义。
下半部分也是类似的,我们对一个数仓表、湖仓表进行了 ad-hoc 并发的更新 c1 和 c2,c1 在 c2 之后提交,但是 c1 在 c2 之前开始,当它们出现冲突之后是 c1 覆盖 c2,还是 c2 覆盖 c1?从目前数据湖方案来说,一般是谁后提交以谁为准,但是在更多的生产场景中我们需要谁先开始以谁为准。这一块时间关系就不展开,有任何疑问可以在用户群里与我们深入交流。
Arctic auto bucketing
在性能方面 Arctic 也做了很多工作,我们目前是基于 Iceberg 的,Iceberg 是非常灵活开放的 Table format,它在 partition 之下没有考虑我的数据以及我的数据对应的更新,应该怎样更好地做映射来提升它的性能。
在 Iceberg 之上我们做了 auto bucketing 的功能,这个功能跟 Hudi 中 file_group 的概念有些类似。不同的是我们没有给用户暴露 file_group 或者 file_index 这样的概念。我们在文件之上提供了分组的功能,是一种可扩展的方式,通过二叉树的扩展方式让每一个节点的数据量尽可能维持在用户配置的大小。比如说 Iceberg 默认配置 128 兆,我们通过后台的一整 optimizing 套机制,会尽可能维护每个 node 的大小向 128 兆靠拢。
![](https://pic4.zhimg.com/80/v2-b4daf109d992f53221d4c320754e2c43_720w.jpg)
当一个 node 数据超过这个范畴之后,我们会尝试把它分裂,之前也提到我们分了 changestore 和 basestore,它们都是按照同样的方式管理,这样在每一个节点之上可以对应到 change 数据和 base 的数据,就能实现更精细的数据映射,数据分析的性能会有一个非常好的提升。
可以看到在 merge-on-read 的过程也可以用到整套机制。2000 年左右伯克利有一篇论文专门描述这种方案,感兴趣的同学也可以自己去了解。
![](https://pic4.zhimg.com/80/v2-5be9a6fd4d9c470be895b0acf0242087_720w.jpg)
Arctic 性能测试
流式湖仓,或者在数据湖上做实时流式数仓的整套实践,目前还没有非常好的 benchmark 工具来定义它的性能怎么样。对这个问题我们也做了很多考虑和探索,目前我们的方案和 HTAP benchmark 采用的思路是一致的,根据 TiDB 的介绍,找到行业里很早就有的 CHbenchmark 这个概念加以改造。
CHbenchmark 支持一个数据库既跑 TPC-C 也跑 TPC-H。从下图左边可以看到,有 6 张表是重合的,既在 TPC-C 中跑也在 TPC-H 中跑,有 3 张表是在 TPC-C 中引用,3 张表只在 TPC-H 中引用。
![](https://pic2.zhimg.com/80/v2-033e71b83e10b9821c742716251616f1_720w.jpg)
基于这套方案我们做了一个改造,首先用 TPC-C 跑数据库,在下面我们再跑一个 Flink CDC 任务,把数据库实时流式地同步到 Arctic 数据湖中,用 Arctic 数据湖构建一个分钟级别数据新鲜度的流式湖仓,在这之上我们再跑 CHbenchmark 中 TPC-H 的部分,这样能得到比较标准的流式湖仓的数据分析的性能。
针对 optimize 前后的 Arctic、Iceberg 和 Hudi 测试的结果(Trino 下测试),我们按阶段做了一个简单的对比,分为 0-30 分钟、30-60、60-90 分钟和 90-120 分钟四组。下图蓝色的部分是没有 optimize 的数据分析的性能,从 0-30 分钟,到最后的 90-120 分钟,延迟从 20 秒降低到了 40 多秒,降低了一半多。而黄色部分有持续合并的 Arctic,性能稳定在 20 秒左右。
![](https://pic4.zhimg.com/80/v2-02cfc67145f4cfd3a37191ae98322dd3_720w.jpg)
灰色的是原生的 Iceberg upsert 方案,0-30 分钟是在 30 秒左右,从 30-60 分钟性能是急剧下降的。为什么 Iceberg 出现了这么大的性能滑坡呢?因为原生 Iceberg 确实没有 insert 数据和 delete 数据的精细化的映射,所以当我们持续写入流式文件之后,每一个 insert file 都会跟 delete file 产生非常多的关联,从而导致我们在 Trino 中做 merge-on-read 的性能急剧下降。后面测 60-90 分钟、90-120 分钟就直接 OOM,跑不出来了。
黄色部分是 Hudi。目前来看 Arctic 和 Hudi 一样,通过后台优化能够保证数据分析的性能,维持在一个比较平稳的数字。目前来看我们通过上层的优化,比 Hudi 要好一些。后续我们也会在官网中把我们整个测试流程和相关配置向大家公开。
Arctic 目前看 mor 性能相比 Hudi 有一定优势,这里我们先不强调 Arctic 做得有多好我们也研究了 Hudi,它有 RO 和 RT 两种模式,前者是只会读合并数据,RT 模式是 merge-on-read 的一种模式。它的 RO 模式和 RT 模式性能差距非常大,所以未来可能会有很大的优化空间。
Arctic roadmap 与总结
最后我们对 Arctic roadmap 以及整个系统做个简单的总结。Arctic 是一个流式湖仓服务,提供分别对应 streaming、lakehouse、service 的核心特性。
streaming 层面我们提供了主键的高效流式更新,我们有数据自分桶、结构自由化的能力,Spark、Trino merge-on-read 的功能,提供分钟级别新鲜度的数据分析。
在 lakehouse 层面我们做到格式的兼容,百分之百兼容 lceberg 和 Hive 的表格式语法,如果有一些功能是 Arctic 没有而 Iceberg 有的,用户只需要切换到 Iceberg catalog,就能够把一张 Arctic 表当作 Iceberg 表来使用,并且我们提供了 base 和 change 两个表的访问方式。
引擎平权支持 Spark 和 Flink 读写数据,支持 Trino 和 Impala 查询数据,目前 Impala 主要是用到 Hive 的兼容特性,可以把 Arctic 表作为一个 Hive 做查询,从而支持 Impala。
![](https://pic3.zhimg.com/80/v2-a6fa4c3d31118d9fbdd63cf1c4195ece_720w.jpg)
在 service 这一块主要强调管理上的功能:
第一个是支持将数据湖和消息队列封装成统一的表,实现流批表的统一,这样用户使用 Arctic 表不用担心从秒级或者毫秒级降低到分钟级别,他依然可以使用数据湖提供毫秒或者秒级的数据延迟的能力。
第二点提供流式湖仓标准化度量,dashboard 和相关的管理工具。
第三点是解决并发写入冲突,实现事务一致性语义。
在管理层面我们聚焦回答下面这几个问题,这些工作还有很长的路要走。
第一个是表的实时性怎么量化,比如说我们搭建一个流式的湖仓表之后,当前的新鲜度是一分钟、两分钟还是多少,是否达到了用户的预期。
第二个怎样在时效性、成本、性能之间给用户提供 trade off 方案。
第三个查询性能有多少优化空间,需要投入多大的资源做这样的事情。
第四点数据优化的资源该怎样量化,怎样最大化利用这些资源。如果用户深入了解 Arctic,会发现我们 optimizing 跟目前 Hudi 其他的有很大不同,首先我们 optimizing 是在平台层面调度的,不是在每一个写入的任务里做的,这样我们可以集中化管理这些数据优化的资源,并且可以提供最快的迭代。比如我们发现通过一些优化能够让合并效率有很大的提升,就可以很快迭代。
最后一点是怎样灵活分配资源,为高优先级来调度资源。
在未来 Core feature 维度的工作,首先我们关注的是不依赖外部 KV 实现 Flink lookup join 功能。我们之前看到的一个架构里,如果在实时场景下做一个维表 join,可能需要一个外部的 KV 做同步,目前我们在做这样的方案,就是不需要做外部的同步了,可以直接基于 Arctic 表来做维表 join。
第二个是流式更新部分列,现在我们主要是通过 CDC 来做 streaming upsert,很多场景,比如特征、大宽表,我们可能需要能够更新部分列。
后面是更多的 optimizer container 支持,比如说 K8s;更多 SQL 语法的支持,比如说 merge into—— 目前我们在 Arctic 层面还没有这样的语法,用户可以把 Arctic 的表当成 Iceberg 表来用,来支持 merge into。未来如果在 Arctic 层面支持了 merge into,它会和 Iceberg 有所不同,因为我们的变更数据首先会进入到 change 空间。
最后一点因为我们的生态位是在数据湖 Table format 之上,所以未来我们会做架构的解耦,去扩展到更多的 Table format,比如 Delta、Hudi。
最后谈谈我们开源的初衷。过去我们做开源可能没有一个非常统一的步调,去年我们领导层下了一个决心,会按照一种更加专注的方式做开源,以 Arctic 这个项目为例,我们不会做任何的商业隐藏。而且从组织架构而言我们团队推进开源也是非常独立的过程,如果可能有商业化会由其他的团队推进。
我们会致力于为开发者、用户、成员构建一个公开、自由的数据湖技术交流社区。当然目前我们主要面向的是国内用户,官网也是以中文为主。希望更多的开发者参与到我们这个项目中来。
这是我今天要分享的全部内容,谢谢大家!
Q&A
主持人:有没有关注过关于 Flink Tablestore 的特性,跟 Arctic 又有怎样的区别?
马进:有。首先大家做的东西都比较相似,去年我们就看到了 Flink 社区里面这样的 proposal。我理解 Flink 一定会做这样的事情,他们也是希望能搭建一套自己完整的生态,就像 Delta 对于 Spark 一样。
虽然是相似的,但是大家的目标是不太一样的,Flink 做这个事对流这个场景而言更加原汁原味,但是肯定不会像我们更多考虑到怎么在 Spark 上,在其他的引擎上做一些事情,怎么在上层提供更多的管理功能。所以抛开一些功能上的重合,我理解大家的初衷或者最终要解决的问题还是会有差异。
主持人:虽然在表现形式上是相似的,但是 Flink tablestore 的这种方式更贴近原生 Flink 的场景,但是我们除了兼容 Flink 的场景之外还会有更多偏向于 Spark 的场景做兼容和支持。
马进:不光是 Spark,我们还提供了 Hive 兼容。如果是 Hive 用户,怎么能让一些 Hive 表比较顺滑地升级到我们湖仓一体新的架构上,这是我们系统去考量的一些东西,在这个过程中怎样提供一些便利的管理功能,提供度量指标,这些可能和 Flink Tablestore 考虑的点是不一样的。
主持人:Arctic 底层刚才讲到是基于 Iceberg 实现的,在代码上有强绑定的关系吗?以后会不会考虑基于其他的 Table format 做这种转换?
马进:我们也经历过一些变化。现在我们自己定的标准首先不会侵入到 format 内部的实现,也不会魔改开源的代码。但早期我们并没有这样明确的目标,会有一些在 Iceberg 上的更改。现在我们代码和 Iceberg 相对来说是可以做一个比较干净的解耦,但是目前我们没有做这个事,比如说 Schema 这些定义用的还是 Iceberg 包里的东西,但是这个东西要解耦是很容易的。这里面有个设计上的初衷,产品要去考虑怎么把数据湖用起来,会有一些考虑,比如 Iceberg 和 Delta 谁更可能成为未来的主流?我们希望用户能免除这样的烦恼,未来我们希望能在上层给用户提供一个统一的他需要的 Lakehouse 方案,下层我们再做这样的选型。
主持人:说白了我们不帮用户做出最终的决定,而是提供更多的可能性,无论未来是 Iceberg 还是 Delta,我们都能用一种比较开放的方式兼容。
马进:这个是长远的,现在我们还会和 Iceberg 结合得紧密一些。
嘉宾简介
马进,网易数帆大数据实时计算技术专家、湖仓一体项目负责人,负责网易集团分布式数据库,数据传输平台,实时计算平台,实时数据湖等项目,长期从事中间件、大数据基础设施方面的研究和实践,目前带领团队聚焦于流批一体、湖仓一体的平台方案和技术演进,及流式湖仓服务 Arctic 项目开源。
Arctic 文档:Arctic (netease.com)
GitHub 地址:GitHub - NetEase/arctic: Arctic is a streaming lake warehouse service open sourced by NetEase
视频观看:流式湖仓服务Arctic介绍by网易数帆马进@Arctic开源发布会_哔哩哔哩_bilibili
交流群:微信添加 “kllnn999” 为好友,注明 “Arctic 交流”