湖仓一体只流于表面,是个笑话?丨话题接力
本文内容依据李呈祥老师和王新春老师的〖deeplus直播:话题接力丨数据仓库、数据湖、湖仓一体应用及趋势探讨〗线上分享演讲内容整理而成。 (文末有回放的方式,不要错过)
近年来,业界开始提出湖仓一体(Data Lakehouse)的概念,彻底打通了数据湖和数据仓库,优势日渐突出。然而,作为一个新兴架构,很多企业的湖仓一体实践仍处在一个早期探索阶段,同时也有不少实践者对其存疑,甚至提出了“湖仓一体是伪命题”的观点。
湖仓一体能否真正落地?有哪些实现难点?是否会成为企业发展的必选项?dbaplus社群邀请到 唯品会 数据平台负责人-王新春、哔哩哔哩 OLAP平台负责人-李呈祥 在云上汇聚,希望通过汇集两位大数据专家的研究成果和实践积累,给大家进一步明确数据仓库、数据湖、湖仓一体的发展方向,提供可参考、可落地的湖仓一体实战经验。
两位老师也列举了各自企业在数据仓库、数据湖、湖仓一体上的发展历程和相关实践,给大家提供参考:
哔哩哔哩和大部分互联网公司一样,之前的大数据平台都是基于开源的Hadoop生态系统。存储用的是HDFS,计算引擎则有Hive,Spark以及Presto等。在我看来,这是一个比较典型的数据湖的架构,从数据的采集到ETL再到数据的处理服务的业务场景。公司内部的运营人员可以基于这些数据去做分析和决策,数据也可以通过特征工程作为AI推荐系统的数据源。
但是,我们也有很多交互分析的需求,为了解决这些需求,我们会引入特定的分布式数仓,引擎使用的是ClickHouse和OLAP引擎,主要是用于支撑我们内部的数据产品、数据服务以及BI报表之类的需求,对于数据的查询效率、查询速度和查询性能要求非常高。
湖仓一体我们大概从一年前开始探索,主要是应用在数据查询加速场景上,具体来说是Hive表查询加速的场景之上,希望能够通过湖仓一体的架构,简化我们整个数据开发的流程,支撑大部分数据分析类的需求。
一是数据的支持能力的变化: 首先传统的数仓建模理论已经有30多年了,建模的方式以及方法也一直在演进。比如多维分析的星型模型、雪花型模型到现在比较流行的建设各种宽表层,从宽表层再到DWS或ADS层等数仓典型的分层架构。存储或计算的方式也从关系型数据库里用于数仓的MPP数据库,向SQL on Hadoop或SQL on 对象存储(云原生)等模式在演进。另外,原有的很多数仓如果是SQL on Hadoop体系,有一个最基本的假设是数据不支持更新,就是数据入仓之后,如果要更新需要把数据重新再刷一遍。而对于数据湖而言,不管是哪一个具体的组件,包括Iceberg、Hudi、Delta Lake,这些组件提供了数据更新的能力,这其实是一个很大的不同之处。
二是数据的时效性的变化: 传统的数据的时效性基本上是T+1,这个+1一般是天级或小时级,还有更多的一些需求会慢慢到分钟级以及秒级,并且希望这些数据的时效性可以越来越快。可以用Streaming的方式处理这些数据,用Batch的方式处理天级或小时级的数据,这就是典型的Lambda架构,但是会有一些重复计算,出现重复的存储、数据口径一致性等问题。
从业务需求发展的角度来说,用户肯定希望消耗更少存储和计算的资源,通过更便捷的加工方式和更快速的数据处理能力完成对于业务的需求。需求和技术的变化会慢慢催生出数据的加工和建设方式的演变,最终能够用一种革新的方式来处理。虽然这些革新的方式从现在看未必那么普适,但还是可以在某些点/方向有适配业务场景,以及利用数据湖的一些技术,在这些场景下体现出它的显著价值。
唯品会从2021年开始引进一些数据湖相关的技术,当时基本上是属于探索的阶段,在这个阶段我们更多是看它到底能够做什么,以及我们实现这项技术的时候还需要做哪些工作。今年我们投入了更多资源,希望它能够完成更多业务上的迭代更新及改造,能够在整个数据加工生产的链路中体现出来一些优势。在这个过程中我们遇到了很多问题,也解决了一些问题,同时还发现有更多问题等着我们通过业务、技术上的改造解决。同时也在业务上的一些推广过程中得到一定收益,这个过程可以认为是痛并快乐着的。
dbaplus社群还搜集了一些数据仓库、数据湖、湖仓一体应用的痛难点,跟两位老师一起探讨:
我们把数仓分为两个阶段,第一阶段就是MPP阶段, 不管是Oracle、Greenplum还是其它MPP数据库来建设整个数仓, 如果 第二阶段是SQL on Hadoop或者SQL on 云原生体系 ,那么我们绝大多数场景还是属于第二阶段。
对于数据湖以及湖仓可以支持增量计算、更新以及更丰富一些做法的场景,至少从我个人角度看,它至少可以演进到2.5阶段的场景。在演进的过程中,可能业务覆盖度的比例相对于整个公司业务的比例还不是很高,也局限在比较确定的一些场景,因此在2.0~2.5的阶段,推广成整体数据生产普适的场景,我们还是有比较多的工作要继续推进。
在业界我们可以看到很多对于湖仓一体优势的介绍,但实际它也有很多不足之处,我们发现这个技术对于业务开发或平台开发的同学都会有一些挑战。
刚刚提到湖仓里很大的不同之处在于支持我们拿到数据的Delta,唯品会是属于电商的场景,我们要拿到更新的数据,我们每天要从算全量的数据变成算Delta的数据,典型的业务场景如计算销售额。消费者购买一件商品,从下单支付到派送到收货再到退货,这个场景历史的时间周期可能会很长,虽然大部分几天之内就能完成,但是少部分订单以及需要有售后的可能会出现跨越的时间跨度要上年的情况。那么此时我们要算订单的销售额,就不能简单地把每天的订单的销售额累加,这样算出来是错误的,算一年的销售额我们可能需要把最近两年甚至三年的订单的销售额全部重新算一遍,那么成本是巨大的。
其实几十亿的订单数据里真正会发生更新的数据分为两类:一类是当天的销售,产生了新订单;第二类是发生的各种变动,比如订单派送、取消、售后、换货等。更新的订单数量其实并不多,如果我们看三年的周期,它可能低于十万分之一,但我们为了算对口径,只能全部重算一遍。
对于数据湖来说,在我可以获取增量数据的情况下,理论上我只需要把变化的订单拿出来重新算一遍,然后和历史的数据做聚合,就能算出准确的销售数字。从数据湖里我们可以增量获取Delta,Delta里有新增、删除等更新,可以分别计算这些数据的值,最终把销售额计算出来。所以从这个角度来看,有了数据湖以后打开了一个很大的想象空间,但实际我们在落地的过程中,它并没有那么简单。
在我们数仓的传统SQL里,我们要去改造它时也遇到了一些很大的挑战:
一是哪些情况下我认为这些数据是增量的,我们的订单有很多状态,但不是所有的状态都认为订单的交易额我们要去掉,这个需要比较,相当于我要去拿之前的数据的version和当前的version进行比较,原生的Hudi是不支持的,那么我们的改造目的就是取得它当前version和前一个version某些数据的diff。
二是我们有很多数据需要能够合并,比如今天新增的订单要加到原来的订单里,删除的订单要从里面减去,有很多数据的合并操作需要去重新实现。
三是数据开发的同学对数据开发的思想要改变,因为原来很多思想都是基于数据是不可变化的,现在需要考虑怎么更新,所以很多模型设计的思路要发生变化,对于数据开发的同学是要重新学习的过程,他要理解什么是增量,怎么去获取增量,这也是我们在实际落地过程中如果要做ETL相关的一些场景时难度很高的地方。现有的湖仓表和原来的 Hive表 的设计思路也是不同的,如果用原来的 Hive表 的设计思路设计湖仓表,可能跑起来比 Hive表 更慢。
而且我们对于湖仓的很多数据还给不出一些非常明确的优化建议,不像传统的 Hive表 ,我们可以根据各种信息明确告诉数据开发的同学应该怎么设计和调优,我们需要把这些工作重新再做一遍,这些都是额外带来的一些问题和挑战。
湖仓一体为底层的大数据平台提供了三个方向的能力支持:
一是湖仓一体支持upsert和delete,也就是支持更新的场景;
二是数据的可见性从之前的天级、小时级可以做到分钟级、秒级;
三是基于Iceberg、Hudi、Delta这种新的表存储格式,提升SQL on Hadoop的分析查询场景的查询性能,使其效率可以达到或者接近专门的分布式数仓。
在B站我们团队基于湖仓一体主要做的也就是以上我说的第三个方向,针对于写成Iceberg格式的表,我们希望它能够做到或者接近于专用的分布式数仓的高效查询效率 ,包括数据分布组织、索引、预计算、计算存储一体化/缓存等整体的增强和优化。它和普通的Hive表其实在用户看起来和用起来基本上是一致的,只是表的存储格式改变了,但是表存储模型下Iceberg提供了很多事务的能力,比如对数据的重新组织和优化,对小文件进行合并排序,并给它建索引等,能够用上之前在SQL on Hadoop这套生态上缺少的数仓的高级特性,并且整个过程对用户而言是完全不需要感知的、透明的。
基于这套方案,我们能够实现数据不用从SQL on Hadoop生态系统出到另外一个存储系统里,就能做到或者接近于专用的分布式数仓的高效查询效率,从而实现降本增效,以比较低的开发和使用成本支撑一些数据服务、报表、 BI等业务场景,所以对于我们来说还是快乐更多,痛比较少。
我们的技术选型是在一年前做的,这三个表存储格式本身迭代发展得也比较快,一年时间变化也比较大。 执行选型的时候我们为什么选择Iceberg?
首先最主要的原因是希望达成我们的目标,基于Iceberg这种表层的格式补上数仓的数据管理、分布索引等高级性能相关的特性,通过加速查询实现降本增效。
其次我们也做了一些调研,Iceberg、Hudi和Delta Lake是基本同时期出现的开源表存储格式项目,Iceberg在三个里面是表存储格式抽象得最好的,包括读写引擎、Table Schema、文件存储格式都是pluggable的,我们可以进行比较灵活的扩展,并保证和开源以及之前版本的兼容性,基于此我们也比较看好该项目的长远发展。Delta Lake和Databricks绑定得比较紧,相对Iceberg和Hudi而言社区其他的参与者比较少,活跃度也比较低。Hudi当时主要还是偏重于数据更新的场景之上,所以我们选择了Iceberg作为哔哩哔哩湖仓一体架构的核心。
随着三个社区的发展,我觉得Iceberg、Hudi、Delta Lake这三个表存储格式的功能其实越来越接近了 ,区别没有很明显,可能也会并存很长一段时间。在湖仓一体或分布式数仓领域,就商业化公司参与度而言,Iceberg的参与者会更多一些,比如Snowflake、Dremio等。其它方面目前三个社区整体都是处于非常活跃的阶段,更新迭代很快,功能上比较明显的短板都会快速补齐。
其实我们做选型的时候都比较早,现在看当时选择某一个选型未必有特别明确的理由,距离我们调研Hudi的时候也已经快两年了。当时Hudi也是一个很早的版本,Iceberg可能会更初期一些,所以大家能力都比较欠缺。现在这三个的差距越来越小, 选型可以从以下方向进行考虑:
第一个方向是考虑自身对于组件的掌握程度, 因为这几个组件并不是开箱即用的傻瓜式使用,需要理解一下组件本身。
第二个方向是看自建还是上云还是其它模式, 选择又会有所不同,因为这些组件有的整合得会更完善一点,有的则稍微落后。
第三个方向是如果直接用PaaS型的数仓, 那么可能又是另外的情况,因为它们可能也是数据湖系列,但是底层并不是Iceberg、Hudi、Delta Lake,而是其它的。
因为目前整个生态湖仓涉及到的组件和技术非常多样,所以 核心还是要评估自己适配的场景以及业务的模式, 再进行决策。 单从技术来说,很难评判一个技术或组件一定比另一个好多少,更多的时候是适合。
首先是和当前大数据平台的兼容, 其实引入的一个最主要的组件就是新的表存储格式,我们还是用统一的HDFS存储,和之前的SQL on Hadoop生态系统无缝兼容,包括基于Spark或者Flink ETL数据接入,SQL/ML/DataSet等各层次API访问以及Presto/Spark/Hive等多种计算引擎的支持。但是从用户视角来说,他看到的就是一个存储格式不同的Hive表。
其次是技术方面的瓶颈, 我们团队做的湖仓一体主要是专注于查询加速,对我们来说,目前基于开源社区版本的Iceberg在这方面还比较欠缺,比如OLAP引擎、索引类型、数据排序组织、预计算等功能特性和能力都不够完善,所以我们自己也在这方面做了很多定制化的增强,以补足这一方面的支撑能力。此外,为了实现查询加速的目标,做到对于数据的组织排序、建索引等,需要有Iceberg的数据管理服务去拉起Spark任务。当前社区并没有这么一个数据管理的角色,所以我们选择了自研,专门用来对Iceberg数据进行智能的数据管理。如果想在企业内部落地湖仓一体,这也是一个需要自研的很重要的服务组件。
如果你要应用公有云上商业化的产品,比如用Databricks,它已经提供了湖仓一体的能力,Snowflake或者国内的阿里云的ADB、MAXcomputer也支持湖仓一体,可以保持湖的灵活性,数据的存储格式是开放的,你也可以用其它开放的数据计算引擎访问它,甚至可以直接从文件系统层面上访问它,同时能够有比较好的产品效率。
如果你是自建的大数据平台,目前来说还是需要有一定的技术上的投入,要看团队内有没有专业的技术人才能够承担这件事情,如果是通过招聘,需要进一步考虑投入的人力以及技术上的成本, 结合规模判断收益投入产出比是否符合预期。
如果是要自己引入,目前来说它还不属于一个直接就可以用的东西,需要有人跟进这件事情,至于投入多少人力成本,根据业务的场景模式和使用的具体情况决定。
如果是在自建的情况下,从我个人的角度来看,除非Hadoop系统真的解决不了你的痛点问题,或者你对于湖仓一体业务上的诉求真的很强,否则我建议再等等。
我们最开始认知的时候,对于湖仓一体的期望很美好, 期望能够改造生产链路,从数据的入仓到计算再到最后数据出去整个完整的链路。但是我们发现要做数据的整个ETL,也就是改造原来的生产链路, 其实挑战非常多,并不像讲的那么简单。 当你真的想把业务搬过来的时候,会发现业务上有些写法难以实现,比如你要考虑做Delta的情况下,可能第一件事情就是SQL不知道怎么写。我们也可以用UDF改写底层的代码让它提供这种能力,但是成本就会很高,并没有期望中那么简单。
在一些专有的场景下,我们发现还是能够达到比较高的收益。比如我们在做Hudi的数仓改造时,我们希望把很核心的一张订单商品宽表的生产时效提升50%,因为它需要前置,准备很多表数据之后,中间要跑各种计算过程,最后再生产这张宽表。那么我们现阶段能够做到的是基本上与原来的表的时效接近或打平。目前看可以通过很多技巧,最终完成使得这张表的时效提升50%的目标。这件事情做完对我们来说有明确的收益,因为这张表的后继任务很多,如果能够在数仓里生产的时候将其提前半小时,那么几乎70%以上的后继都能提前半小时,YARN集群上的资源的开销也会更均衡,资源利用率在高峰时间甚至能提升5%。我们去做其它技术优化时,要达到5%的优化程度可能需要非常大的成本开销。
在你的业务场景里基于湖仓一体的架构能否成功落地,归根结底还是要看你想要用它来解决什么类型的问题。在当前这个阶段可能有些问题上湖仓一体已经解决得很好了,而有些问题如果能解决收益会很大,但是在当前阶段不一定能够解决, 所以你对于是否要落地和选型要有一个比较清楚的认知,而不是盲目地觉得湖仓一体比当前的SQL on Hadoop大数据架构好。 否则你在落地过程中可能会碰到很多坑,可能也会不好处理。
在具体的场景上,有的是希望用湖仓一体解决一些Hadoop架构解决不了的问题,另一类是希望通过湖仓一体降本增效,降低计算和存储的成本,成为一种技术驱动力。
就我们自己的经验而言,B站作为一个互联网公司,Append Only数据在整体的数据里是很大的,然后从log或埋点等数据进来之后,经过ETL进行数仓建模,然后从ODS到DWD再到ADS,最终提供数据产品、数据服务、报表、BI等,对于这个数据流程里分析层的数据,我们基于湖仓一体的架构能够对其进行查询上提效,比如原来我可能需要200台机器才能满足查询的需求,现在只需要100台甚至50台即可满足,从而通过湖仓一体降低了机器的成本,这是一个比较大的收益。
另外一方面,如果你对数据的实时性有要求,可能之前离线的都是天表或小时表,现在希望能够实现分钟级数据对外可见,当前这个阶段湖仓一体也已经可以比较好地解决这个问题了。
我理解的一个方向是分布式的OLAP引擎, 它原来的数据存储格式是自己的,在分布式数仓中支持CSV、JSON、ORC、PARQUET等开放存储格式,将数据的处理流程从ETL转换为ELT,数据注入到分布式数仓后,在分布式数仓中进行业务数仓的建模工作,这是一种湖仓一体的路径。 另一个方向是基于SQL on Hadoop这一套,加上开放的查询引擎和新引入的开放表存储格式达到分布式数仓的处理效率, 比如在B站我们基于Trino加Iceberg做湖仓一体。
对于第一种湖仓一体的路径,一个超大数据量的ETL任务基于Spark、Hive去跑,它的可靠性会非常高。但是如果你把它放到一个分布式OLAP引擎里去跑,且不说它的可靠性和高可用,它可能会对于你的Adhoc 查询 产生比较大的这种影响。 OLAP引擎的资源隔离也没有单独的分布式处理引擎 在这一方面也可以做得更好,现在很多OLAP引擎在强化资源隔离能力,避免大查询占用小查询的资源。
另外一方面它的灵活性也会稍微差一些,它对用户提供的可能是SQL这一层的入口,基于开放的计算引擎有不同的入口,你可以自带数据进行处理。
具体要看面临的场景、数据量级以及业务的复杂度, 对于大多数数据量不是很大的公司,可能各种OLAP引擎结合湖仓的技术就能够解决问题,因为绝大多数数据的输出是报表,或者是一些ADHOC的场景。
基于SQL on Hadoop体系用各种湖仓的技术叠加起来的第二种路径,可能有更多支持的业务场景,以及更多功能特性。比如我要做一些模型的特征,因为很多模型的特征都比较宽,如何把实时和离线的特征数据聚合起来,如何在更新或迭代的时候做得更快?很多时候我们可能会重度依赖一些框架用于一些特征的加工及生成,如Flink、Spark。做数据分析依赖OLAP引擎如Doris或Presto,假如框架层面不提供整合数据湖的能力,要自己做还是有比较大的工作量。
如果更多是面向数据产品的应用场景,且你有一个强有力的MPP架构,它跑起来也够快,甚至不需要做ETL任务就能够将数据表秒级响应,大部分情况就能够满足业务的需求。那么一定程度上能避免ETL任务过多导致的重复计算、重复存储、口径不一致等问题。
首先实事求是地说,这个观点有些“标题党”。 我们的确能够享受到湖仓一体带来的一些收益,也能够在成本、效率等方面看到它的不同之处。
从唯品会的引入目的来说,我们希望湖仓一体的技术把任务变成增量的存储和计算之后,理想化的情况下,我们能够大幅度降低数仓体系在机器上的消耗,包括计算资源的消耗和存储资源的消耗。因为在大数据领域不管是数仓还是OLAP引擎这些场景里,我们都要投入比较多的机器,每年都要新增采购相应的机器补充到我们的资源池里面,以支持业务的需求,湖仓一体从某种程度上可以使我们看到有一些新的手段可以提升机器的效率。 虽然我们在实际的落地过程中遇到了问题和挑战,但是我觉得大的方向和趋势是对的。
如果本身体量规模不是很大,整个数仓的存储或计算的集群只有一两百台机器,可能节约的量就体现不出来。但是机器数量比较庞大的企业如果能提升10%~20%,产生的边际效应就足够大了。更多时候我们判断湖仓一体或者是其他新技术的引入,是看对我们而言能够产生多大的边际效应,单一的场景或业务可能看到的改变比较小,业务数量足够多才能看到明显的改变。
这个观点说“湖和仓只是提升了两者的数据传输频率,湖仓物理上仍然分存两处”, 我觉得这个可能是对于湖仓一体概念上理解的不是特别一致。
之前我们说数据湖就是SQL on Hadoop这套系统,数据仓库就是分布式的OLAP引擎比如Clickhouse,然后数据从一个Hive表同步到Clickhouse上,这个算是一个入仓的过程。数据在HDFS上,要存一份Hive表的数据,在Clickhouse里要存一份数据,Clickhouse表上的数据可能会成为一个数据孤岛,也无法比较高效地和在HDFS上的Hive表进行关联,进行Adhoc数据探索。
所以湖仓一体打通了湖和仓,比如我们基于Trino加Iceberg这种格式,Iceberg里实际上存的也是PARQUET、ORC这种数据,它也是存在HDFS上的,并且你可以用Trino这个计算引擎去关联一个ORC表和一个Iceberg表,同时能够查开放的数据存储格式,使其效率可以达到或者接近专门的分布式数仓,且没有数据孤岛, 这是我理解的湖仓一体。
湖仓一体更多时候是作为一个底层基座和提供底层能力,数据中台更多时候是体现湖仓一体价值的输出。 也就是说,数据中台一些底层的建设是基于湖仓一体做的,从而提升数据输出的能力,比如查询的性能,再通过数据中台展现,因为是数据中台把数据真正输出给业务侧使用。
我觉得湖仓一体和数据中台的关系,就是通过湖仓一体底层的运行能力增强和提升数据中台的建设,从而带来更多好处,比如让它的架构然后变得更简单。 比如我们B站已经在做的就是我们的数据中台团队基于湖仓一体架构,建设一个统一的取数服务,以API方式对外提供服务,在系统或平台上包装成业务侧的概念,比如定义成一个指标,然后用户通过API访问指标。基于湖仓一体绝大部分数据能够以Iceberg数据格式存储,基于Trino查询可以达到秒级的响应速度,满足绝大部分的用户的取数需求。
在没有湖仓一体之前,比如我直接基于Hive/Spark去查询一个ORC表,可能需要几十秒甚至更长时间,那么可能满足不了用户的需求,所以就需要做一些其它改进,比如我有一个同步任务,可以导出到Clickhouse里,然后由Clickhouse响应。现在能够直接由湖仓一体的架构响应,指标定义在一个Hive表里,存储格式是Iceberg,就能够满足用户的需求,整个数据状态和技术架构会变得更加简化。
技术栈你可以在云上实施,也可以在IDC里实施。一些云上的供应商已经支持相应的技术方案,可以直接用,如果是在线IDC则需要基于开源的技术栈自建。
从我的个人经验来说,如果你评估你的机器量小于100台,那么建议选择上云,上云成本的支出并不会增加很多,甚至可能成本会更低。如果是机器量庞大的公司,选择上云成本支出会明显增加,因为自建的IDC机器可以用得更久,云厂商很多时候为了达到同样的性能水平,机器淘汰速度会更快,所以在机器成本也就是裸机成本这一项会更高。
特别鸣谢
↓点这里 可 回看本期直播