基于数据湖格式构建数据湖仓架构 ——毕岩 阿里巴巴技术专家

本文涉及的产品
云原生数据仓库AnalyticDB MySQL版,基础版 8ACU 100GB 1个月
简介: ——毕岩阿里巴巴技术专家

一、数据湖&数仓&湖仓

image.png

新架构的提出往往是为了解决老架构存在的问题,而数据湖的出现也是为了解决传统数仓架构遗留的问题。

阿里云对数据湖的定义为:数据湖是统一存储池,可对接多种数据输入方式,可以存储任意规模的结构化、半结化、非结化数据也可以无缝对接到多种计算分析处理的引擎和平台,可以直接对数据做处理和分析,打破数据孤岛,洞察业务价值等。同时,阿里云还提供了冷热分层转换能力,覆盖数据全生命周期

定义可以提炼出数据湖的公共能力:

第一,具备统一中心化的存储和数据管理。

第二,支持非结构化、半结化和结构化等各类型数据

第三,支持 SQL ML等各类查询、计算、分析。

第四,支持大规模的数据

第五,开放开源的格式比如ParquetORC

传统的数仓架构仅支持结构化和半结构化,只能提供 SQL 语法导致对于音频视频图等非结构化数据的处理能力较弱,也无法直接对接到机器学习和深度学习框架。

为了解决数仓引入问题,数据湖架构被提出。而数据湖本身存在一些问题

第一,安全数据湖将所有数据都做了统一存储,缺乏完备的操作审计,且只能做到文件级别的权限控制,因此存在安全性问题。

第二,质量。数据湖天然支持同一份数据同时被数据分析师、数据科学家等不同的角色使用同时还引入了批流两种方式的写入如果没有合适的方法保证事务的质量,保证其一致性,则会带来可靠性问题。

第三,性能。不同于数仓可以使用索引缓存以及优化后特定的存储格式加速查询原生的数据湖查询性能较弱,

第四,成本。数仓的数据格式是封闭自定义的,因此在机器在学习和深度学领域无法很好地应用。

基于以上挑战,数据湖引入了存储层。而引入新的引擎组件必然带来一系列学习和使用成本,以及后续的运维和管理成本等。因此,最终从数据湖衍生出数据湖仓架构。

image.png

仓架构是在数据湖上拓展了原本仓的能力,融合了两者的优势,弥补劣势,达到了灵活性、安全和高性能的统一。

湖仓架构的底层继承了数据湖架构统一存储数据的能力,使能够承载结构化和非结化数据,同时允许 BI AI 的任务直接在上面运行。湖仓架构的关键在于中间层封装了数据湖的存储层,包括数据湖管理和元数据服务的能力。

通过权限审计工作解决安全问题以及降低部分数据湖管理成本的工作,可以借助中间层的数据湖管理和元数据服务模块。性能和质量上多流读写的事务性保证可以借助于数据湖格式本身解决。

另外,数仓架构能够支持数据湖的数据增加或删除字段等schema 变更来适配数据的变更,支持数据的审计和回溯。存算分离的特性也更加有利于企业做细粒度的成本控制,同时也利于比如在EMR环境下集群的版本升级或管理等。然而存算分离之后会引发数据读取 IO开销增加,可以通过引入大数据缓存Alluxio以及阿里云的JindoFS 来解决。

image.png

上图展示了传统的数仓数据湖和数据湖仓的区别。可以看到原本数据湖在成本数据可靠性监管安全以及性能上问题都可以通过数仓的方式得以解决。

二、数据湖格式

数据湖格式是作用在数据湖仓架构之下、在数据真实的存储层之上元数据管理之下的一层数据存储

image.png

数据湖的很多特性都由数据湖格式来承载,这DeltaLakeHudiIceberg这两年兴起的主要原因和背景。

DeltaLakeDatabricks公司提出,近期宣布了将全功能开源,一次性放出很多大家期待的featureIcebergNetflix开源,其设计更开放,在国外的场景上应用更佳Hudi Uber开源当前在国内社区比较活跃,其社区风格较为激进,会进行快速功能迭代,因此功能丰富。Hudi只是将自己作为数据湖的存储层,而是一个平台,内置了很多管理的服务。

image.png

数据湖格式的关键实现是:表的元数据不再存放在比如 HiveMetaStore服务里,而是和数据一起放在本地的 filesystem针对于每一次表的变更都会提交新的事务日志记录对湖格式表的修改schema的变化和数据文件的变化等。基于以上设计,再结合并发控制协议,能够更好地实现并发控制,拓展 TimeTravel等能力。

image.png

经过了几年的发展,三个湖格式的整体功能已经基本一致。

其中HudiIceberg支持的Merge on Read主要解决写数据时遇到的写放大现象。比如想要更新某包含 1 万条数据的文件里的 1000 条数据需要将 1000 条更新之后的值连同 9000 条没有被修改的数据一起再写回到新的文件数据湖格式会将一个版本标记为废弃,将最新版本标记为生效。新版本内9000数据原封不动被保留下来,这就是写放大现象。

 Hudi能够 1000 条新增的数据通过行存的形式写入增量文件,在查询时合并增量文件和 base 文件,得到全视图最新版本的数据。

 DeltaLake 220可以delta表作为 CDC source 产生changedata 给下游交付,再做使用。湖管理功能比如合并小文件,用户无需用户再另起任务,能够减少用户的使用和管理成本。Hudi以及 EMR 版本的 DeltaLake都已实现该功能,社区版目前尚未跟进。

image.png

生态上,三个格式也在持续布局和完善。三者都已具备基于 Spark Flink 的读写功能在查询引擎支持上略有不同,比如 icebergprestoJindo上已经支持写的功能。DeltaLake在云厂商的支持以及云catalog 支持上推动比较好。

不管哪一种湖格式,能够实现实时 Sync 实时入湖和入仓,后续可以进一步做 ETL 处理,比如 ODS 层到 DWD DWS 层的数据的转换。支持 Spark OLAP 引擎查询提供近实时的 OLAP 能力。

image.png

湖格式场景一:SCD

SCD保存随着时间缓慢变化的维度值的变更信息。举个例子,用户和常驻地,用户可能隔几天几小时会变更所在地信息随着时间变化。在此类场景,可能有些数仓无法只提取最新数据只能提取到某个历史时刻用户在何地

SCD根据对新值的处理方式,定义了多种类型TypeType0指只保留原来的值,新值丢弃;Type1只保留最新值,将历史值全部丢弃;Type2以行存的形式保存所有记录Type3增加新的字段来保留前版本和当前版本。

本示例使用Type2增加两个字段,用于标识某条记录生效范围,或者也可以通过布尔值直接表示是否生效。

初始表格如最上方表格所示,需要将原有 ID 标记为无效,新数据标记为有效如果 ID 不存在原表里,则以新增的方式插入。基于以上策略得到的表入上图最下方表格所示。

针对上述示例,传统数仓的实现逻辑比较复杂,很难保证其事务性。而数据湖格式通过语法在一次事务中完成对数据的删除修改新增插入。

上图右侧为具体语法实现。Using部分的数据通过 when mached()when not mached then()部分语法,按照逻辑写入到 target 表里when mached语法表示:当匹配到某条记录之后,会对这条记录做删除或修改when not mached then后面可以加谓词,对数据做插入。

image.png

湖格式场景二:G-SCD

另一类场景,比如只需要知道用户某天内最后在什么地方,即只需知道固定时间段内用户最新值,可以通过湖格式的TimeTravel解决。我们基于 EMR 胡格式的TimeTravel能力实现了G-SCD解决方案,是基于固定粒度缓慢变化

此前基于 Hive 的解决方案如下:首先一条实时流通过不断获取增量的数据写入到增量表里。再将T+1的增量表和原始表的 T 分区数据作合并,产生离线表的 T+1分区。通过分区值查询 T+1分区即可获知这一天用户最新的值。该方案存在较重的数据冗余以及资源浪费,因为 TT+1 的数据大量重复。

G-SCD的解决方案如下:首先通过 MySQL 将变量信息拖至 Kafka 消费Kafka数据,通过 Spark Streaming batch 的形式做提交。该方案会要求每一个被提交到 Delta commit 只包含业务快照数据,让每一个业务快照和delta版本做关联。比如先提交了一个 T 时刻的版本,又提交了一个T时刻,后面提 T+1时刻可以通过查询第二个 T时刻的 TimeTravel得到 T时刻数据。 此外,我们对Spark Streaming做了升级,可按照业务快照做拆分,比如按天级别拆成两天数据,一天一天提交,保证提交秩序

该方案无需添加辅助字段只需原生的表结构即可解决。同时不存在大量数据冗余,能够借助于 Spark Delta本身的查询优化提升查询效率。

image.png

湖格式场景三:CDC

上图定义了流式的 ETL 其中表中包含userIDnamecity三个字段。通过 user_city 表和 user_name 表做 join name 字段接入并产生下游的表。再按照 city 表做聚合得到所在的城常州人口数据。

针对以上需求,此前常用的方案为:首先获取全量的 user_city 表,将它user_name 表做 join ,以 override 的形式写到 user_name_city 表。然后按照 city group by 重写后面的 city_population表,每一步都全量数据

CDC方案如下:首先通过 user_name_city表的次变更提取出其change data,将其与user_name 表做 join 更新到 user_name_city 表。user_name_city 表在这次变更中产生以下变更:用户 1 从北京变杭州用户 5 新增数据,位于武汉。因此,再往下游到 city_population 表里,需要对于北京-1,对杭州和武汉+1,得到其新的常驻人口。

CDC方案需要user 信息操作还需要表里的其他字段信息,比如 city 字段等以及获取该记录完整的前和后才能下游做处理。

银行场景下,比如有A B 两个账户 A 账户全天没有任何变化, B 账户全天操作了几百次但最终金额没有变化。此类场景需要追溯每一次变更才有意义。

image.png

EMR内部,HudiDelta都是基于 CDLF 的思路实现CDC充分权衡了读写两端的性能结合了数据湖格式的事务性特点以及变更的有效映射关系提出的CDLF方案,其核心在于必要时会持久化 CDC数据类似于数据湖触发器的形式,数据湖可以通过 create trigger 语法来对insertdelete update 操作做触发,将前和旧写到一张insert表里后续可直接查询insert表得到其 CDC 数据。

以上方案增加了写开销但在查询时避免了表 diff ,具有较高的传输效率而该方案依然存在可优化的点:

首先,尽可能复用已有的数据,避免所有场景所有写操作都持久化举个例子,首次表的 insert 每一条数据都是先插入才进行操作因此没必要双写一份数CDC数据集只需下载原有的数据并进行拼接,将其标记为 insert 或前值为空然后返回即可再比如删除分区场景,整个分区的数据都被删除,因此只需将所有数据加载进来,拼接上删除操作,并置新值空返回即可

其次,针对主键场景,仅持久化主键(和操作类型),查询时再提取旧值和新值。

image.png

当前,湖格式的使用还存在一些挑战:

第一,学习和使用成本。不同的数据湖格式有不同的实现,在读写场景上会有不同,会带来较大的学习成本和后续调优成本。

第二,湖格式统一了批和流,因此必然会有小文件过期文件清理问题,管理成本增加

第三,湖格式依然处于发展阶段,迭代较快前后版本无法能保证完全兼容。

第四,无法真正地满足OLAP场景的查询性能要求。

第五,引擎之间并不互通,元数据也没有打通,生态集成不够成熟。

第六,业务和客户对于数据湖格式的引入依然持保守观望的态度,更多的使用场景有待挖掘打磨

三、阿里云EMR+DLF构建湖仓架构

image.png

上图为DLF数据湖仓架构图。

最底层由OSS存储作为数据的统一存储层往上是关键的由 DLF 数据湖构建开放开源的数据湖格式数据湖缓存加速JindoFS 三者共同提供的数据湖管理和优化层再往上是由开源和阿里云自研的产品组成的弹性计算引擎层,提供了基于 BI AI 能力最上阿里云数据开平台 DataworksEMR提供的开发层,提供了完备的数据开发体系和数据治理平台。

image.png

DLF数据湖构建是阿里云提出的全托管数据湖服务,提供了湖仓架构下必需的能力。它提供了全托管的统一元数据,借助于该能力可以无缝对接到 EMR 上的各类开源引擎阿里云的数据集成平台以及阿里云的数仓产品等,实现湖仓一体,避免数据孤岛现象。

统一的权限服务能够帮助适配到多个查询引擎和多个产品,为数据的访问和操作提供了安全的保证。标准的入湖模板可以对接到 MySQL BinlogKafka等多个 source 实现一键入湖,可直接保存成湖格式的表后续再在 EMR 或其他产品上做处理和查询。元数据发现能力可以直接扫描底层的filesystem ,发掘未被管理和记录的数据来消除沉没数据。

据湖管理能力直接针对于数据湖格式提供的管理能力,包括自动化解决小文件以及历史过期文件带来的一系列管理和运营。

DLF会监听湖格式每一次提交 commit 感知每一次变化,实时分析各种维度的指标包括文件数平均文件大小有效/无效文件占比等。

image.png

EMR的数据湖格式提供了丰富的SQL语法,包括 Partition相关、DPOOptimizeTimeTravel等,支持SavepointRollBack等,拓展了Spack SQL支持Streaming SQL语法。EMR解决了湖格式存在的问题,保证了格式和普通的 Hive 表的功能和场景性能一致。即使在存在schema 变更的情况下也能够保证正确实时地同步到相关元数据服务。三种湖格式都可对接到 DLF 支持阿里云其他产品的查询。

我们也在积极拥抱社区,向社区贡献了很多关键 feature比如Spark3.0 Merge Into语法Delta支持Hive查询的delta-connectors以及HudiSpark SQL支持和Hudi CDC

Q&A

Q:湖格式产品支持 CDC也是通过 Binlog 实现的吗?

A湖格式产品支持CDC是将自己的表作为 CDC source 提供服务。主要用于构建完整的一套增量场景。此前通过 SQL Binlog 只是将数据库changedata做入湖而已,并不能继续支持下游的场景。

Q请问 Hudi 现在支持使用 Java reader读取数据吗?

A:支持,可以通过 Java 的方式读写数据,性能上不如Flink Spark大数据引擎。

相关实践学习
AnalyticDB MySQL海量数据秒级分析体验
快速上手AnalyticDB MySQL,玩转SQL开发等功能!本教程介绍如何在AnalyticDB MySQL中,一键加载内置数据集,并基于自动生成的查询脚本,运行复杂查询语句,秒级生成查询结果。
阿里云云原生数据仓库AnalyticDB MySQL版 使用教程
云原生数据仓库AnalyticDB MySQL版是一种支持高并发低延时查询的新一代云原生数据仓库,高度兼容MySQL协议以及SQL:92、SQL:99、SQL:2003标准,可以对海量数据进行即时的多维分析透视和业务探索,快速构建企业云上数据仓库。 了解产品 https://www.aliyun.com/product/ApsaraDB/ads
相关文章
|
6天前
|
运维 持续交付 API
从零构建微服务架构:一次深度技术探索之旅####
【10月更文挑战第28天】 本文记录了作者在从零开始构建微服务架构过程中的深刻技术感悟,通过实战案例详细剖析了微服务设计、开发、部署及运维中的关键要点与挑战。文章首先概述了微服务架构的核心理念及其对企业IT架构转型的重要性,随后深入探讨了服务拆分策略、API网关选型、服务间通信协议选择、容器化部署(Docker+Kubernetes)、以及持续集成/持续部署(CI/CD)流程的设计与优化。最后,分享了在高并发场景下的性能调优经验与故障排查心得,旨在为读者提供一套可借鉴的微服务架构实施路径。 ####
39 3
|
15天前
|
Kubernetes 负载均衡 Docker
构建高效后端服务:微服务架构的探索与实践
【10月更文挑战第20天】 在数字化时代,后端服务的构建对于任何在线业务的成功至关重要。本文将深入探讨微服务架构的概念、优势以及如何在实际项目中有效实施。我们将从微服务的基本理念出发,逐步解析其在提高系统可维护性、扩展性和敏捷性方面的作用。通过实际案例分析,揭示微服务架构在不同场景下的应用策略和最佳实践。无论你是后端开发新手还是经验丰富的工程师,本文都将为你提供宝贵的见解和实用的指导。
|
5天前
|
监控 前端开发 JavaScript
探索微前端架构:构建可扩展的现代Web应用
【10月更文挑战第29天】本文探讨了微前端架构的核心概念、优势及实施策略,通过将大型前端应用拆分为多个独立的微应用,提高开发效率、增强可维护性,并支持灵活的技术选型。实际案例包括Spotify和Zalando的成功应用。
|
14天前
|
监控 API 持续交付
构建高效后端服务:微服务架构的深度探索
【10月更文挑战第20天】 在数字化时代,后端服务的构建对于支撑复杂的业务逻辑和海量数据处理至关重要。本文深入探讨了微服务架构的核心理念、实施策略以及面临的挑战,旨在为开发者提供一套构建高效、可扩展后端服务的方法论。通过案例分析,揭示微服务如何帮助企业应对快速变化的业务需求,同时保持系统的稳定性和灵活性。
44 9
|
14天前
|
Kubernetes 负载均衡 Docker
构建高效微服务架构:Docker与Kubernetes的完美搭档
本文介绍了Docker和Kubernetes在构建高效微服务架构中的应用,涵盖基本概念、在微服务架构中的作用及其实现方法。通过具体实例,如用户服务、商品服务和订单服务,展示了如何利用Docker和Kubernetes实现服务的打包、部署、扩展及管理,确保微服务架构的稳定性和可靠性。
58 7
|
13天前
|
Kubernetes 负载均衡 Docker
构建高效微服务架构:Docker与Kubernetes的完美搭档
【10月更文挑战第22天】随着云计算和容器技术的快速发展,微服务架构逐渐成为现代企业级应用的首选架构。微服务架构将一个大型应用程序拆分为多个小型、独立的服务,每个服务负责完成一个特定的功能。这种架构具有灵活性、可扩展性和易于维护的特点。在构建微服务架构时,Docker和Kubernetes是两个不可或缺的工具,它们可以完美搭档,为微服务架构提供高效的支持。本文将从三个方面探讨Docker和Kubernetes在构建高效微服务架构中的应用:一是Docker和Kubernetes的基本概念;二是它们在微服务架构中的作用;三是通过实例讲解如何使用Docker和Kubernetes构建微服务架构。
50 6
|
12天前
|
负载均衡 应用服务中间件 nginx
基于Nginx和Consul构建自动发现的Docker服务架构——非常之详细
通过使用Nginx和Consul构建自动发现的Docker服务架构,可以显著提高服务的可用性、扩展性和管理效率。Consul实现了服务的自动注册与发现,而Nginx则通过动态配置实现了高效的反向代理与负载均衡。这种架构非常适合需要高可用性和弹性扩展的分布式系统。
19 4
|
11天前
|
前端开发 API UED
深入理解微前端架构:构建灵活、高效的前端应用
【10月更文挑战第23天】微前端架构是一种将前端应用分解为多个小型、独立、可复用的服务的方法。每个服务独立开发和部署,但共同提供一致的用户体验。本文探讨了微前端架构的核心概念、优势及实施方法,包括定义服务边界、建立通信机制、共享UI组件库和版本控制等。通过实际案例和职业心得,帮助读者更好地理解和应用微前端架构。
|
13天前
|
负载均衡 应用服务中间件 nginx
基于Nginx和Consul构建自动发现的Docker服务架构——非常之详细
通过使用Nginx和Consul构建自动发现的Docker服务架构,可以显著提高服务的可用性、扩展性和管理效率。Consul实现了服务的自动注册与发现,而Nginx则通过动态配置实现了高效的反向代理与负载均衡。这种架构非常适合需要高可用性和弹性扩展的分布式系统。
28 3
|
15天前
|
前端开发 JavaScript 测试技术
Android适合构建中大型项目的架构模式全面对比
Android适合构建中大型项目的架构模式全面对比
31 2

热门文章

最新文章