关于存储:数据湖分析如何面向对象存储OSS进行优化

45次阅读

共计 8220 个字符,预计需要花费 21 分钟才能阅读完成。

简介:最佳实际,以 DLA 为例子。DLA 致力于帮忙客户构建低成本、简略易用、弹性的数据平台,比传统 Hadoop 至多节约 50% 的老本。其中 DLA Meta 反对云上 15+ 种数据数据源(OSS、HDFS、DB、DW)的对立视图,引入多租户、元数据发现,谋求边际老本为 0,收费提供应用。DLA Lakehouse 基于 Apache Hudi 实现,次要指标是提供高效的湖仓,反对 CDC 及音讯的增量写入,目前这块在加紧产品化中。DLA Serverless Presto 是基于 Apache PrestoDB 研发的,次要是做联邦交互式查问与轻量级 ETL。

背景

数据湖以后在国内外是比拟热的计划,MarketsandMarkets _(https://www.marketsandmarkets.com/Market-Reports/data-lakes-market-213787749.html)_市场调研显示预计数据湖市场规模在 2024 年会从 2019 年的 79 亿美金增长到 201 亿美金。一些企业曾经构建了本人的云原生数据湖计划,无效解决了业务痛点;还有很多企业在构建或者打算构建本人的数据湖。Gartner 2020 年公布的报告显示_(https://www.gartner.com/smarterwithgartner/the-best-ways-to-organize-your-data-structures/)_目前曾经有 39% 的用户在应用数据湖,34% 的用户思考在 1 年内应用数据湖。随着对象存储等云原生存储技术的成熟,一开始大家会先把结构化、半结构化、图片、视频等数据存储在对象存储中。当须要对这些数据进行剖析时,会抉择比方 Hadoop 或者阿里云的云原生数据湖剖析服务 DLA 进行数据处理。对象存储相比部署 HDFS 在剖析性能下面有肯定的劣势,目前业界做了宽泛的摸索和落地。

一、基于对象存储剖析面临的挑战

1、什么是数据湖

Wikipedia 上说数据湖是一类存储数据天然 / 原始格局的零碎或存储,通常是对象块或者文件,包含原始零碎所产生的原始数据拷贝以及为了各类工作而产生的转换数据,包含来自于关系型数据库中的结构化数据(行和列)、半结构化数据(如 CSV、日志、XML、JSON)、非结构化数据(如 email、文档、PDF、图像、音频、视频)。

从下面能够总结出数据湖具备以下个性:

  • 数据起源:原始数据、转换数据
  • 数据类型:结构化数据、半结构化数据、非结构化数据、二进制
  • 数据湖存储:可扩大的海量数据存储服务

2、数据湖剖析计划架构

次要包含五个模块:

  • 数据源:原始数据存储模块,包含结构化数据(Database 等)、半结构化(File、日志等)、非结构化(音视频等);
  • 数据集成:为了将数据对立到数据湖存储及治理,目前数据集成次要分为三种状态表面关联、ETL、异步元数据构建;
  • 数据湖存储:目前业界数据湖存储包含对象存储以及自建 HDFS。随着云原生的演进,对象存储在扩展性、老本、免运维有大量的优化,目前客户更多的抉择云原生对象存储作为数据湖存储底座,而不是自建 HDFS。
  • 元数据管理:元数据管理,作为连贯数据集成、存储和剖析引擎的总线;
  • 数据分析引擎:目前有丰盛的剖析引擎,比方 Spark、Hadoop、Presto 等。

3、面向对象存储剖析面临的挑战

对象存储相比 HDFS 为了保障高扩展性,在元数据管理方面抉择的是扁平的形式;元数据管理没有保护目录构造,因而能够做到元数据服务的程度扩大,而不像 HDFS 的 NameNode 会有单点瓶颈。同时对象存储相比 HDFS 能够做到免运维,按需进行存储和读取,构建齐全的存储计算拆散架构。然而面向剖析与计算也带来了一些问题:

  • List 慢:对象存储依照目录 / 进行 list 相比 HDFS 怎么慢这么多?
  • 申请次数过多:剖析计算的时候怎么对象存储的申请次数费用比计算费用还要高?
  • Rename 慢:Spark、Hadoop 剖析写入数据怎么始终卡在 commit 阶段?
  • 读取慢:1TB 数据的剖析,相比自建的 HDFS 集群竟然要慢这么多!
  • ……

4、业界面向对象存储剖析优化现状

下面这些是大家基于对象存储构建数据湖剖析计划遇到的典型问题。解决这些问题须要了解对象存储相比传统 HDFS 的架构区别进行针对性的优化。目前业界做了大量的摸索和实际:

  • JuiceFS:保护独立的元数据服务,应用对象存储作为存储介质。通过独立元数据服务来提供高效的文件治理语义,比方 list、rename 等。然而须要部署额定服务,所有的剖析读取对象存储依赖该服务;
  • Hadoop:因为 Hadoop、Spark 写入数据应用的是基于 OutputCommitter 两阶段提交协定,在 OutputCommitter V1 版本在 commitTask 以及 commitJob 会进行两次 rename。在对象存储下面进行 rename 会进行对象的拷贝,老本很高。因而提出了 OutputCommitter V2,该算法只用做一次 rename,然而在 commitjob 过程中断会产生脏数据;
  • Alluxio:通过部署独立的 Cache 服务,将近程的对象存储文件 Cache 到本地,剖析计算本地读取数据减速;
  • HUDI:以后呈现的 HUDI、Delta Lake、Iceberg 通过 metadata 的形式将 dataset 的文件元信息独立存储来躲避 list 操作,同时提供和传统数据库相似的 ACID 以及读写隔离性;
  • 阿里云云原生数据湖剖析服务 DLA:DLA 服务在读写对象存储 OSS 下面做了大量的优化,包含 Rename 优化、InputStream 优化、Data Cache 等。

二、DLA 面向对象存储 OSS 的架构优化

因为对象存储面向剖析场景具备下面的问题,DLA 构建了对立的 DLA FS 层来解决对象存储元信息拜访、Rename、读取慢等问题。DLA FS 同时反对 DLA 的 Serverless Spark 进行 ETL 读写、DLA Serverless Presto 数据交互式查问、Lakehouse 入湖建仓数据的高效读取等。面向对象存储 OSS 的架构优化整体分为四层:

  • 数据湖存储 OSS:存储结构化、半结构化、非结构化,以及通过 DLA Lakehouse 入湖建仓的 HUDI 格局;
  • DLA FS:对立解决面向对象存储 OSS 的剖析优化问题,包含 Rename 优化、Read Buffer、Data Cache、File List 优化等;
  • 剖析负载:DLA Serverless Spark 次要读取 OSS 中的数据 ETL 后再写回 OSS,Serverless Presto 次要对 OSS 下面建仓的数据进行交互式查问;
  • 业务场景:基于 DLA 的双引擎 Spark 和 Presto 能够反对多种模式的业务场景。

三、DLA FS 面向对象存储 OSS 优化技术解析

上面次要介绍 DLA FS 面向对象存储 OSS 的优化技术:

1、Rename 优化

在 Hadoop 生态中应用 OutputCommitter 接口来保障写入过程的数据一致性,它的原理相似于二阶段提交协定。

开源 Hadoop 提供了 Hadoop FileSystem 的实现来读写 OSS 文件,它默认应用的 OutputCommitter 的实现是 FileOutputCommitter。为了数据一致性,不让用户看到两头后果,在执行 task 时先把后果输入到一个长期工作目录,所有 task 都确认输入实现时,再由 driver 对立将长期工作目录 rename 到生产数据门路中去。如下图:

因为 OSS 相比 HDFS 它的 Rename 操作非常低廉,是 copy&delete 操作,而 HDFS 则是 NameNode 上的一个元数据操作。在 DLA 的剖析引擎持续应用开源 Hadoop 的 FileOutputCommitter 性能很差,为了解决这个问题,咱们决定在 DLA FS 中引入 OSS Multipart Upload 个性来优化写入性能。

3.1 DLA FS 反对 Multipart Upload 模式写入 OSS 对象

阿里云 OSS 反对 Multipart Upload 性能,原理是把一个文件宰割成多个数据片并发上传,上传实现后,让用户本人抉择一个机会调用 Multipart Upload 的实现接口,将这些数据片合并成原来的文件,以此来进步文件写入 OSS 的吞吐。因为 Multipart Upload 能够管制文件对用户可见的机会,所以咱们能够利用它代替 rename 操作来优化 DLA FS 在 OutputCommitter 场景写 OSS 时的性能。

基于 Multipart Upload 实现的 OutputCommitter,整个算法流程如下图:

利用 OSS Multipart Upload,有以下几个益处:

  • 写入文件不须要屡次拷贝。能够看到,原本低廉的 rename 操作曾经不须要了,写入文件不须要 copy&delete。另外相比于 rename,OSS 的 completeMultipartUpload 接口是一个十分轻量的操作。
  • 呈现数据不统一的几率更小。尽管如果一次要写入多个文件,此时进行 completeMultipartUpload 依然不是原子性操作,然而相比于原先的 rename 会 copy 数据,他的工夫窗口会缩短很多,呈现数据不统一的几率会小很多,能够满足绝大部分场景。
  • rename 中的文件元信息相干操作不再须要。通过咱们的统计,算法 1 中一个文件的元数据操作能够从 13 次降落到 6 次,算法 2 则能够从 8 次降落到 4 次。

OSS Multipart Upload 中管制用户可见性的接口是 CompleteMultipartUpload 和 abortMultipartUpload, 这种接口的语义相似于 commit/abort。Hadoop FileSystem 标准接口没有提供 commit/abort 这样的语义。

为了解决这个问题,咱们在 DLA FS 中引入 Semi-Transaction 层。

3.2 DLA FS 引入 Semi-Transaction 层

后面有提到过,OutputCommitter 相似于一个二阶段提交协定,因而咱们能够把这个过程形象为一个分布式事务。能够了解为 Driver 开启一个全局事务,各个 Executor 开启各自的本地事务,当 Driver 收到所有本地事务实现的信息之后,会提交这个全局事务。

基于这个形象,咱们引入了一个 Semi-Transaction 层 (咱们没有实现所有的事务语义),其中定义了 Transaction 等接口。 在这个形象之下,咱们把适配 OSS Multipart Upload 个性的一致性保障机制封装进去。另外咱们还实现了 OSSTransactionalOutputCommitter,它实现了 OutputCommitter 接口,下层的计算引擎比方 Spark 通过它和咱们 DLA FS 的 Semi-Transaction 层交互,构造如下图:

上面以 DLA Serverless Spark 的应用来阐明 DLA FS 的 OSSTransactionalOutputCommitter 的大体流程:

  1. setupJob。Driver 开启一个 GlobalTransaction,GlobalTransaction 在初始化的时候会在 OSS 上新建一个暗藏的属于这个 GlobalTransaction 的工作目录,用来寄存本 job 的文件元数据。
  2. setupTask。Executor 应用 Driver 序列化过去的 GlobalTransaction 生成 LocalTransaction。并监听文件的写入实现状态。
  3. Executor 写文件。文件的元数据信息会被 LocalTransaction 监听到,并贮存到本地的 RocksDB 外面,OSS 近程调用比拟耗时,咱们把元数据存储到本地 RocksDB 上等到后续一次提交可能缩小近程调用耗时。
  4. commitTask。当 Executor 调用 LocalTransaction commit 操作时,LocalTransaction 会上传这个 Task 它所相干的元数据到 OSS 对应的工作目录中去,不再监听文件实现状态。
  5. commitJob。Driver 会调用 GlobalTransaction 的 commit 操作,全局事务会读取工作目录中的所有元数据中的待提交文件列表,调用 OSS completeMultipartUpload 接口,让所有文件对用户可见。

引入 DLA FS 的 Semi-Transaction,有两个益处:

  • 它不对任何计算引擎的接口有依赖,因而前面能够比拟不便的移植到另外的一个计算引擎,通过适配能够将它所提供的实现给 Presto 或者其它计算引擎应用。
  • 能够在 Transaction 的语义下增加更多的实现。例如对于分区合并的这种场景,能够退出 MVCC 的个性,在合并数据的同时不影响线上对数据的应用。

2、InputStream 优化

用户反馈 OSS 申请费用高,甚至超过了 DLA 费用(OSS 申请费用 = 申请次数×每万次申请的单价÷10000)。考察发现,是因为开源的 OSSFileSystem 在读取数据的过程中,会依照 512KB 为一个单位进行预读操作。例如,用户如果程序读一个 1MB 的文件,会产生两个对 OSS 的调用:第一个申请读前 512KB,第二个申请读前面的 512KB。这样的实现就会造成读大文件时申请次数比拟多,另外因为预读的数据是缓存在内存外面的,如果同时读取的文件比拟多,也会给内存造成一些压力。

因而,在 DLA FS 的实现中,咱们去掉了预读的操作,用户调用 hadoop 的 read 时,底层会向 OSS 申请读取从以后地位到文件结尾整个范畴的数据,而后从 OSS 返回的流中读取用户须要的数据并返回。这样如果用户是程序读取,下一个 read 调用就天然从同一个流中读取数据,不须要发动新的调用,即便程序读一个很大的文件也只须要一次对 OSS 的调用就能够实现。

另外,对于小的跳转(seek)操作,DLA FS 的实现是从流中读取出要跳过的数据并抛弃,这样也不须要产生新的调用,只有大的跳转才会敞开以后的流并且产生一个新的调用(这是因为大的跳转读取 - 抛弃会导致 seek 的延时变大)。这样的实现保障了 DLA FS 的优化在 ORC/Parquet 等文件格式下面也会有缩小调用次数的成果。

3、Data Cache 减速

基于对象存储 OSS 的存储计算拆散的架构,通过网络从远端存储读取数据依然是一个代价较大的操作,往往会带来性能的损耗。云原生数据湖剖析 DLA FS 中引入了本地缓存机制,将热数据缓存在本地磁盘,拉近数据和计算的间隔,缩小从远端读取数据带来的延时和 IO 限度,实现更小的查问延时和更高的吞吐。

3.1 Local Cache 架构

咱们把缓存的解决逻辑封装在 DLA FS 中。如果要读取的数据存在于缓存中,会间接从本地缓存返回,不须要从 OSS 拉取数据。如果数据不在缓存中,会间接从 OSS 读取同时异步缓存到本地磁盘。

3.2 Data Cache 命中率进步策略

这里以 DLA Serverless Presto 来阐明如何进步 DLA FS 的 local Cache 的命中率进步。Presto 默认的 split 提交策略是 NO\_PREFERENCE,在这种策略上面,次要思考的因素是 worker 的负载,因而某个 split 会被分到哪个 worker 下面很大水平上是随机的。在 DLA Presto 中,咱们应用 SOFT\_AFFINITY 提交策略。在提交 Hive 的 split 时,会通过计算 split 的 hash 值,尽可能将同一个 split 提交到同一个 worker 下面,从而进步 Cache 的命中率。

应用 \_SOFT\_AFFINITY\_策略时,split 的提交策略是这样的:

  1. 通过 split 的 hash 值确定 split 的首选 worker 和备选 worker。
  2. 如果首选 worker 闲暇,则提交到首选 worker。
  3. 如果首选 worker 忙碌,则提交到备选 worker。
  4. 如果备选 worker 也忙碌,则提交到最不忙碌的 worker。

四、DLA FS 带来的价值

1、Rename 优化在 ETL 写入场景的成果

客户在应用 DLA 过程中,通常应用 DLA Serverless Spark 做大规模数据的 ETL。咱们用 TPC-H 100G 数据集中的 orders 表进行写入测试,新建一个以 o\_ordermonth 字段为分区的 orders\_test 表。在 Spark 中执行 sql:”insert overwrite table \`tpc\_h\_test\`.\`orders\_test\` select * from \`tpc\_h\_test\`.\`orders\`”。应用同样的资源配置,应用的 Spark 版本一个为开源 Spark,另外一个为 DLA Serverless Spark,将它们的后果进行比照。

从图中能够得出:

  • 这次优化对算法 1 和算法 2 都有比拟大的晋升。
  • 算法 1 和算法 2 开启这个个性当前都会失去优化,然而算法 1 更显著。这是因为算法 1 须要进行两次 rename,并且有一次 rename 是在 driver 上单点进行的;算法 2 是各 executor 进行分布式 rename 操作且只有进行一次。
  • 在以后这个数据量下,算法 1 和算法 2 在开启这个个性之后,差距没有那么显著。两种形式都不须要进行 rename 操作,只不过是 completeMultipart 是否是在 driver 上单点执行(算法 2 咱们的革新是 completeMultipartUpload 在 commitTask 的时候执行),大数据量可能仍会有比拟大的影响。

2、InputStream 优化在交互式场景的成果

DLA 客户会应用 DLA 的 Serverless Presto 对多种格局进行剖析,比方 Text、ORC、Parquet 等。上面比照基于 DLA FS 以及社区 OSSFS 在 1GB Text 及 ORC 格局的拜访申请次数。

1GB Text 文件剖析的申请次数比照

  • Text 类调用次数升高为开源实现的 1 /10 左右;
  • ORC 格局调用次数升高为开源实现 1 / 3 左右;
  • 均匀来看能够节俭 OSS 调用费用 60% 到 90%;

3、Data Cache 在交互式场景的成果

咱们针对社区版本 prestodb 和 DLA 做了性能比照测试。社区版本咱们抉择了 prestodb 0.228 版本,并通过复制 jar 包以及批改配置的形式减少对 oss 数据源的反对。咱们对 DLA Presto CU 版 512 核 2048GB 通社区版本集群进行了比照。

测试的查问咱们抉择 TPC-H 1TB 数据测试集。因为 TPC- H 的大部分查问并不是 IO 密集型的,所以咱们只从中挑选出合乎如下两个规范的查问来做比拟:

  1. 查问中蕴含了对最大的表 lineitem 的扫描,这样扫描的数据量足够大,IO 有可能成为瓶颈。
  2. 查问中不波及多个表的 join 操作,这样就不会有大数据量参加计算,因此计算不会先于 IO 而成为瓶颈。

依照这两个规范,咱们抉择了对 lineitem 单个表进行查问的 Q1 和 Q6,以及 lineitem 和另一个表进行 join 操作的 Q4、Q12、Q14、Q15、Q17、Q19 和 Q20。

能够看到 Cache 减速能治理在这几个 query 都有显著的成果。

五、云原生数据湖最佳实际

最佳实际,以 DLA 为例子。DLA 致力于帮忙客户构建低成本、简略易用、弹性的 数据平台,比传统 Hadoop 至多节约 50% 的老本。其中 DLA Meta 反对云上 15+ 种数据数据源(OSS、HDFS、DB、DW)的对立视图,引入多租户、元数据发现,谋求边际老本为 0,收费提供应用。DLA Lakehouse 基于 Apache Hudi 实现,次要指标是提供高效的湖仓,反对 CDC 及音讯的增量写入,目前这块在加紧产品化中。DLA Serverless Presto 是基于 Apache PrestoDB 研发的,次要是做联邦交互式查问与轻量级 ETL。DLA 反对 Spark 次要是为在湖上做大规模的 ETL,并反对流计算、机器学习;比传统自建 Spark 有着 300% 的性价比晋升,从 ECS 自建 Spark 或者 Hive 批处理迁徙到 DLA Spark 能够节约 50% 的老本。基于 DLA 的一体化数据处理计划,能够反对 BI 报表、数据大屏、数据挖掘、机器学习、IOT 剖析、数据迷信等多种业务场景。

版权申明:本文内容由阿里云实名注册用户自发奉献,版权归原作者所有,阿里云开发者社区不领有其著作权,亦不承当相应法律责任。具体规定请查看《阿里云开发者社区用户服务协定》和《阿里云开发者社区知识产权爱护指引》。如果您发现本社区中有涉嫌剽窃的内容,填写侵权投诉表单进行举报,一经查实,本社区将立即删除涉嫌侵权内容。

正文完
 0