本文将系统地介绍 lakehouse、table format 概念,阐述湖仓一体作为数据湖流批一体的解决方案,可以发挥哪些价值。在这个价值驱动下,我们过去两年开发了 arctic 这个流式湖仓服务,并在今年下半年开源。
湖仓一体拓展了数据中台和 dataops 的边界,让业务基于数据湖,数据中台也能做流式更新;实时数仓,让数据湖能够具备传统数仓,kudu,doris 的能力,为业务极大地降本提效,欢迎感兴趣的同学咨询和交流。
前数据湖是什么
数据湖这个概念最早由 Pentaho 创始人兼 CTO James Dixon 在 2010 年提出,从当时背景看,这个点子主要是为了推销自家公司基于 hadoop 的 BI 产品方案,时至今日,虽然 Pentaho 已被日立公司收购,这位大佬也另谋出处,而数据湖的含义已远远超出原先的定义,经过各个大厂,尤其是 AWS,Azure 这类公有云厂商的加持,基于数据湖已衍生出非常多样的工具和方法论。
简单说,我们可以把数据湖当做一个存储各类结构化、半结构化和非结构化数据的池子,这个池子可以是私有化的 hadoop 集群,也可以是云端的对象存储,因为我们要存储体量非常大的原始数据和明细数据,这个池子的成本必须足够低,开启 EC 的 HDFS 或对象存储无疑是最佳选择。这个大需要多大?我们用 AWS 提供的一张图来说明:
有了很大的池子存储原始数据和明细数据,数据分析师再也不用担心数据无法溯源,明细丢失的问题,但是按照传统的 BI 方法论,依然需要将数据湖的数据导入到数仓中,才能构建出终端想要的数据集市,那么为什么我们不能放弃旧框架,直接在数据湖上做分析,不是更快更省?
于是乎,数据湖开始了红红火火的十年,在过去十多年中发生了很多标志性事件,我们将数据湖过去十年的发展拆为两个阶段:
第一个五年(2010-2015)打地基,像 mapreduce,spark,flink 这些计算引擎让数据湖之上的 ETL,数据清洗和加工变得简单,parquet、orc 这类列存文件格式,impala、presto、trino 这些基于数据湖的 OLAP 引擎让数据湖之上的数据分析触手可得。
第二个五年(2015-2020)造建筑,不管是云端还是私有环境,各种数据模型,研发工具 ,治理平台玩地风生水起,网易有数、阿里 Dataworks 都是在这个时期诞生的数据中台产品。总体来看,数据湖技术经过五年的打地基,五年的造建筑,目前基于数据湖的工具和方法论已经非常成熟,比如网易做大数据的同学,很多人都接触过有数,或者直接使用过 hadoop、hive。
与几十年根基的传统数仓相比,数据湖近十年发展历程可谓占尽天时地利人和,越来越多的企业在强调数字化转型,越来越多的业务需要大数据帮助决策,此为天时;强大的扩展性,让任何企业都可以通过堆机器来应对爆炸的数据体量,不被任何商业公司绑架,不管你需不需要数仓,你可能都需要一个数据湖,此为地利;hadoop 开源体系,给用户带来了丰富的生态资源,也给企业培养了海量的大数据人才,大家喜欢开源,此为人和,另外,AI、机器学习、数据挖掘这类非标业务非常依赖生态资源的加持,数据湖在这方面有得天独厚的优势。
但同时,数据湖缺乏标准化的服务,生态内的组件大多各自为战,这带来了几个问题:
建筑造地累,比如有数在产品侧需要对接非常多的组件,每个组件都有自己的玩法,架构难免臃肿,人效上不去,当然如果产品不做这些事,就得业务自己做,人效更低;
会导致数据沼泽问题,哪些表在给哪些业务用,哪些数据有浪费,有重复建设,这些都必须在上层定制方案,基础设施这一层缺乏有效的度量和管理支撑,过去企业分享数据中台效果,动辄节省一大半的成本,说明数据湖之上的沼泽问题是非常严重的;
对流和实时场景支持有限,因为数据湖的生态中没有支持行级更新的服务,行业内基本上用数据湖做离线数仓,实时数仓会选择其他方案;
数据质量,因为数据湖非常开放,并且本身会存很多原始数据,在数据质量方面有天然不足,需要上层产品在质量保障方面多加考量。
火爆的湖仓一体
湖仓一体是个舶来词,英文叫 lakehouse, 由 databricks 公司首先在2020年3月提出,在 databricks 的理念中,传统数据湖在批计算,AI,机器学习等领域有丰富的资源和实践,但是在流计算,数据质量和数据治理方面相较于传统数仓有较大不足,为此 databricks 提供了 lakehouse 平台,基于数据湖之上提供不弱于传统数仓的能力,也能享受数据湖在 AI,机器学习,批计算上的积累。
Databricks 作为一家商业化公司来讲 lakehouse 的故事,必然有营销的成分在,但必须承认 lakehouse 这个概念已经深入人心,包括 databricks 的老对手 snowflake,也在讲自己是 lakehouse。感兴趣的同学建议看看 Databricks 工程师最早提出 lakehouse 的博客:
What Is a Lakehouse?
说到 lakehouse,就必须提到 table format 的概念,Table format 最早由 iceberg 提出,现在基本成为行业共识, table format 是什么?简单概括:
Table format 定义了哪些文件构成一张表,这样任何引擎都可以根据 table format 查询和检索数据;
Table format 规范了数据和文件的分布方式,任何引擎写入数据都要遵照这个标准,通过 format 定义的标准支持 ACID,模式演进等高阶功能。
目前国内外同行将 delta、iceberg 和 hudi 作为数据湖 table format 的对标方案,在 databricks 的故事中,delta 是 lakehouse 的存储底座,所以 table format 和 lakehouse 有非常密切的关系,我们有理由相信,lakehouse 方案应当是基于数据湖 table format,涵盖数据研发和数据治理的一整套方案。
湖仓一体有多火,关注行业动态的小伙伴应该会有切身感受,比如从今年开始基本上任何有体量的大会、论坛、meetup 都会组织湖仓一体相关的分会场,我们也能看到各个大厂在这个方向上的积极探索和实践,在 gartner 发布 Hype Cycle™ for Data Management 权威报告中,lakehouse 目前处于跃升期位置,相比于成熟期的 deta lakes,lakehouse 未来还有 3-5 年的发展成熟周期:
还有一份报告值得关注,在 2021 (2022 的报告还未发布)最新发布的数据库魔力象限中,主打 lakehouse 产品的 databricks 和 snowflake 携手进入领导力第一象限,而去年这份报告中,只有 snowflake 处于挑战者的位置:
Lakehouse 不光在技术圈受捧,在资本圈也是鼎鼎有名,巴老爷子加持的 snowflake 千亿神话自不必说,databricks 经过多轮融资之后,也达到了 380 亿美金的估值。就在前不久,delta2.0 完全开源了(过去只开源了一部分),并且推出了一系列新功能,感兴趣的同学可以看下我这篇针对 delta2.0 的分析:
从 Delta 2.0 开始聊聊我们需要怎样的数据湖?
为什么做 Arctic
2020 年开始,通过用户走访和行业调研,我们开始尝试用 flink + iceberg 打造流批一体数据湖的方案,首要的目标是先构建存储的流批统一,在流批一体的数据湖之上,再去探索代码的流批一体,但是在实践中发现,iceberg 作为 table format,直接拿来匹配流批一体的需求还存在很大的 GAP,arctic 这个项目便是在这个背景下产生的。
3.1 企业需要湖仓一体
流批一体和湖仓一体是什么关系,这是过去两年被问的最多的问题。
简单说,流批一体是需求,湖仓一体是方案,就好比我说我想吃甜的东西,你拿给我一块蛋糕,甜是流批一体,蛋糕是湖仓一体。我们可以蛋糕是甜的,但不能是甜的东西就一定是蛋糕,从 lakehouse 提出的背景看,湖仓一体一定是流批一体,但流批一体不一定基于数据湖,事实上很多传统数仓都具备流批一体的能力。
企业为什么需要湖仓一体,可以拆成两个问题:
企业为什么需要流批一体
为什么要在数据湖上做这个事
我们来看看目前主流的流批共存的架构是怎么样的:
场景中用 hive 做批表,kafka 做流表,实时场景下需要用户构建数据库同步到 hbase 的实时任务,需要用户实现 join hbase 维表的流计算任务,把数据写到支持实时更新的 kudu 中,最后由业务根据实时和离线的需要选择查询 kudu 表还是 hive 表,在此之前,用户需要分别在数据模型中建表,使用 kudu 的工具建表,并且自己处理两个系统的差异。在这个架构中,用户遭受了割裂的体验,并且需要在上层做很多工作。
在这套 lambda 架构中,用户使用 hive 和离线开发工具构建离线数仓,使用 kudu,hbase 和实时开发平台构建实时任务,相同的业务逻辑构建了两套数据模型,维护两套数仓和两套任务链路,造成人效和资源的浪费,语义的二义性也会给维护带来更大的成本,对数据分析师,算法工程师,数据科学家,去熟悉两套规范和工具,理解更多的底层概念也是一项很大的挑战。比如对网易云音乐而言,数据分析师和算法工程师很多,怎样尽可能提效和降本是一个很有意义的课题,而对一些规模有限的业务团队,人力紧张,也可能没有多余的预算来搭建两套系统,既快且省可能是第一位的诉求。
理解了流批一体的必要性,那么为什么要基于数据湖做流批一体?
第一数据湖是个兜底的存储中心,具有极强的弹性伸缩能力,符合“省”的要求,第二过去我们围绕数据湖已经搭建了非常丰富的工具,而且现在依然在向 dataops 的方向持续演进,基于这套方法论也沉淀了非常多的规范和实践,如果基于数据湖做流批一体,数据中台上的很多能力可以复用,快速上手,符合业务对“快”的需求。
反之如果我们使用其他数仓做流批一体,比如 doris,相当于在数据湖之外又构建了一个数据孤岛,在依然需要数据湖的情况下,业务需要自己处理 doris 和数据湖的传输和一致性,没有从根本上解决问题。
3.2 Table format 不等于湖仓一体
我们从数据分析的可用性,数据加工的实时性,湖仓的管理三个方面来说明 table format 与我们需要的 lakehouse 之间的 gap。
3.2.1 数据分析可用性
与 Hive 相比,delta/iceberg/hudi 最核心的不同是在表格式中抽象出快照的概念,表的任何数据变更都会构造出新的快照,delta/iceberg/hudi 通过快照的隔离实现数据写入的 ACID 和读取的 MVCC,更好地支持数据实时摄取和计算,如下图所示:
Table format 是数据湖之上比 hive 更进一步的元数据封装,遵循所读即所写的原则,而在用户的读写之间应当有一个标准化的服务,比如在流和实时场景下,会在数据湖中写入很多碎片文件,这些小文件会导致读性能的急剧下降,在 chbenchmark中,我们发现流式写入 2 小时就会导致 olap 性能下降 1 倍以上,不管是数据去重还是小文件合并,我们需要需要一套持续优化的服务来保障数据分析持续可用。
3.2.2 实时数据加工
湖仓一体的特性让批和流的数据加工、数据分析、科学计算、机器学习都能在数据湖中完成,在这几个环节中,数据加工是最基础的步骤,流批一体的数据加工可以让 BI 和 AI 共享 lakehouse 高人效,低成本,强弹性的红利。
目前生产环境中大多使用 hive 和 kafka 分别作为批表和流表选型,实时场景下再搭配 flink 和 kudu 这类支持行级更新的列存数据库做实时数仓方案,用消息队列的优势在于毫秒到秒级的数据时效性,如果我们用 lakehouse 替换掉 hive 和 kafka,在离线数仓和批计算上,可以做到平替,但是在实时数仓和流计算上,由于数据湖的增量读有分钟级延迟,会出现毫秒/秒级的时效性到分钟级时效性的降级。而且从实践上讲,以 kafka 或 pulsar 作为流表实现更加成熟,这令数据湖在实时加工链路中天然吸引不足。
在大量用户调研后,我们发现用户大多能接受数据分析分钟级别的时效性,但对端到端的处理延迟有更高的要求,尤其对数据开发同学,KPI 指标可能是构建的数据建设的复用度,低时效性的数据处理可能丧失对更多场景的吸引,同时面对复杂的数据分层场景,会让端到端的延迟更加不可控。
另一个实时数据加工的问题是维表关联,就是我们俗称打宽的场景,在上文的 lambda 架构中,当用户需要维表关联时,往往需要引入一套 hbase 或 redis 这样的 KV 系统,数据开发同学、算法工程师不光要耗时耗力学习和使用 kv,还需要自己构建数据库到 kv 的同步,接收和处理这些同步任务的报警,处理 kv 数据的序列化反序列化,严重降低了数据开发和算法工程师的幸福度。
在 databricks 的理念中,lakehouse 能做到开箱即用的流批一体,但显然用户期望的流批一体和 delta、iceberg 这类 table format 之间还有较大的 gap,用户对 lakehouse 的期望既要兼顾到端到端的延迟,数据打宽时也要能像离线 join 一样做到即插即用。
3.2.3 怎么做湖仓管理
上文提到,小文件是典型的湖仓管理要解决的问题,过多的小文件会让 OLAP 性能下降,HDFS 的 NN 不堪重负。而当我们在数据湖之上构建更多的实时数仓,会面临更多成本、时效性和性能的管理需求:
表的时效性怎么量化,是否达到用户预期?
湖仓表当前的查询性能有多少可优化空间?
数据优化的资源怎样量化,怎样最大化利用?
怎样灵活分配资源,为高优先调度资源?
区别于 MPP 架构的传统数仓,湖仓是个天然存算分离,弹性伸缩的架构,过去部署一套 greenplum,部署了几台机器,就用几台机器,如果发现容量或性能不足,就去扩容,数据迁移。对这种传统存算一体的架构,对应的管理系统目标是尽可能把内部的运作黑盒化,对外提供一些度量和指标来衡量系统的健康度或性能。
而在湖仓中,首先这套管理系统是缺失的,hive 以及现在的数据湖 table format 归根到底只是定义了表在数据湖上的元数据形态,并没有动态的湖仓管理机制,其次如果我们想做一套湖仓管理系统,思路和存算一体的 MPP 数据库也会有所区别,比如湖仓在后台进行的数据优化动作,用户需要为这些弹性的优化行为花钱,而这个钱会直接作用在湖仓的时效性和性能上,存算分离的管理系统需要为用户更加透明地梳理好时效性,性能,成本之间的关系:
这套湖仓管理系统,需要在保障性能、可用性的前提下,利用好数据湖弹性伸缩的能力帮助用户最大限度降本,为用户花出去的每分钱负责。
Arctic 是什么
我们聊了企业为什么需要流批一体和湖仓一体,也聊到了 table format 和湖仓一体之间的 GAP,生产场景中会存在的需求和问题,Arctic 便是我们团队对这些需求和问题的答案。
Arctic 目前已经开源,我们对 arctic 目前的定位是流式湖仓服务,是基于 lakehouse 开箱即用的流批一体服务,流式强调在数据湖之添加了更多实时的能力,如更加优化的 CDC 摄取,流式更新,生产可用的实时合并,对用户无感的流式数据自优化等,服务强调 arctic 是搭建在 table format 之上的管理服务,如上文所属,arctic 管理服务聚焦在为用户梳理时效性,性能以及成本之间的关系,帮助用户做好容量规划,数据管理和治理。目前 arctic 是搭建在 iceberg 之上,理论上说,arctic 未来也可以基于 delta 和 hudi。
Arctic 架构如下图所示:
可以看到,Arctic 的核心组件包含 AMS 和 Optimizer,在 arctic 中,AMS 被定义为新一代 HMS,AMS 管理 Arctic 所有 schema,向计算引擎提供元数据服务和事务 API,以及负责触发后台结构优化任务。
Arctic 作为流式湖仓服务,会在后台持续进行文件结构优化操作,并致力于这些优化任务的可视化和可测量,优化操作包括但不限于小文件合并,数据分区,数据在 Tablestore 之间的合并转化。
Optimizer container 是 optimizing 任务调度的容器,目前生产环境主要是在 yarn 上调度,支持扩展 optimizer container 实现调度到 k8s 或其平台。Optimizer group 用于资源隔离,optimizing container 下可以设置一个或多个 optimizer group,也可以通过 optimizer group 实现优先级的功能,在 yarn 上 optimizer container 对应队列。
篇幅关系不再对 arctic 的架构与概念进一步展开,感兴趣的同学可以移步我们的文档,后续我也会在其他的文章里聊聊 arctic 在架构设计中的考量,与其他产品的差异。
能用 Arctic 做什么?
Arctic 的目标是开箱即用的流批一体:
与原先流批割裂的 lambda 架构相比,arctic 用存储统一了数据生产的链路,arctic 表既可以作为离线表给 spark 用,也可以作为流表给 flink 用,还可以用 impala/trino 的 OLAP 引擎查询 arctic 表,构建数据集市。值得一提的是,arctic 的流表能够做到毫秒到秒级,arctic 将用户需要的消息队列,作为 broker service 封装到 arctic 的管理体系里,用户只需要在创建表的时候指定是否需要引入队列,在后续的使用中即可透明无感地用到消息队列实时分发的能力,arctic 在对接 flink 的 connector 中,封装了消息队列与数据湖的双写和一致性保障。
在 AP 性能上,arctic 通过 optimizer 机制实现表的结构自优化,在我们的 benchmark 测试中,流式写入 iceberg 表 1 个小时以后,因为小文件问题,以及一些不完善,性能下降会非常厉害,1.5 小时候数据已经跑不出来了,arctic 的平均延迟维持在 20s 左右,而 hudi 30s 左右(平均延迟越小,性能越好),详细的 benchmark 报告可以移步:
Arctic 流批一体的能力可以拓展数据中台,或 dataops 的边界,更直观点说,用户可以直接用各种有数的中台工具来实现流批一体,比如今年我们在帮有道做的替换 doris,和传媒一起做的替换 clickhouse,业务在使用之前的系统时,缺乏高效率的工具,还要为这些独立部署的资源买单,切到 arctic 之后,由于数据湖高度弹性的能力,和低成本的特性,可以给用户省钱提效。
Arctic 不光可以用在大数据场景,今年调研发现,在线业务也有一些需要存储大体量的历史数据,或者 AP 和 TP 混用的场景,比如风控场景需要存储非常多日志清洗后的数据,而这些数据全部存储在 ES 里成本会失控,我们和云音乐团队一起做了一个数据湖与 ES 混合使用的方案,数据湖来兜底,会存储非常久的数据,并且是实时入湖,在我们测量下,用数据湖来实现冷热分离,占用的空间小 XX 倍,成本上则带来几十倍的提升。
期望与规划
要做到开箱即用的流批一体,arctic 还有不少的工作要做。
比如不依赖外部 kv 的维表关联,在前不久发布的 arctic v0.3.1 版本中,我们发布了这项功能的 beta 版本,在一些维表不是很大的场景下,可以做到生产可用,未来还需要做哪些优化工作,已经在 roadmap 里,再比如 inline upsert 功能,让 flink 任务可以流式更新大宽表中的部分列,从而代替状态过大的多流 join,这两个是我们今年在流场景下想要重点打造的功能。完整的 roadmap 记录在 这里 。
在批场景,我们已经支持了相当一部分业务,通过 spark 的读时合并让业务能够独到准实时的数据,用户也可以通过有数提供的 impala 对接 arctic 实现分钟级时效性的实时数仓,用 trino 的用户,可以将 arctic 的 trino connector 集成到自己的 trino 集群中,我们的小伙伴会做好对接工作。
未来 arctic 也将不断丰富管理功能(这块在 lakehouse 领域还比较空白),arctic 作为网易数帆重点打造的一个开源项目,非常欢迎内外部的开发者能够关注、使用和参与,一起打造行业领先的湖仓管理系统,未来一年我们极有可能尝试在 apache 孵化。