解耦存储层和分析层

在大数据流行之初,Hadoop作为事实上的大数据平台,HDFS充当存储层,而Hive充当分析层。Hadoop能够存储几百TB的数据,并可以对半结构化数据进行SQL之类的查询,而且速度在当时已足够快了。

后来,随着数据量增长到新的规模,企业的需求变得更加雄心勃勃,即用户现在期望更快的查询时间,更好的可扩展性,易于管理等等。这时,Hive和HDFS开始为新的更好的技术平台让路。

为了解决Hadoop的复杂性和扩展性方面的挑战,业界现在正转向一种分解的架构,使用REST API将存储层和分析层松耦合起来。这使得每一层在扩展和管理方面都更加独立,并允许为每一项工作使用更合适的工具。例如,在这个分解的模型中,用户可以选择对批处理工作负载使用Spark进行分析,而对SQL繁重的工作负载使用Presto,Spark和Presto都使用相同的后端存储平台。

这种方法现在正迅速成为标准。常用的存储平台是对象存储平台,如AWS S3、Azure Blob存储、GCS、Ceph、MinIO等等。分析平台从简单的基于Python和R的笔记本到Tensorflow、Spark、Presto、Splunk、Vertica等多种多样。

新的分解模型通常在可扩展性和易于管理方面更好。这种方法在架构上也非常适合,但仍有数据一致性和管理方面的挑战需要解决。

(1) Files或Tables

分解模型是指存储系统将数据视为对象或文件的集合,但是终端用户对数据的物理排列不感兴趣,他们想要看到数据的更合乎逻辑的视图。RDBMS数据库在实现这种抽象方面做得很好。随着大数据平台逐渐成为未来的数据平台,现在人们期望这些系统能够以一种用户友好的方式行事,即不强制用户了解物理存储的任何信息。

(2) SQL接口

如上所述,用户不再愿意考虑低效率的底层平台。例如,现在数据湖是ACID兼容的,这样终端用户就不会有额外的开销来确保与数据相关的保证。

(3) 变更管理

在这种规模下管理数据的另一个非常重要的方面是,能够回滚并查看何时发生了什么变化,以及检查特定的细节。目前,使用对象存储的版本管理可以实现这一点,但正如我们前面所看到的,这是在较低的物理细节层,在较高的逻辑级别上可能没有用处。现在用户期望在逻辑层看到版本控制。

可用性挑战和数据一致性需求导致了一个新的软件项目类别。这些项目位于存储平台和分析平台之间,在以本地方式处理对象存储平台的同时,为最终用户提供强ACID保证。其中比较引人注目的一些项目,包括Delta Lake、Apache Iceberg、Apache Hudi和Apache Hive。

Delta Lake

Delta Lake是一种基于文件的开源存储格式,它提供了ACID事务、可扩展的元数据处理,并统一了流数据和批数据处理。Delta Lake是由Databricks开发的,它与Spark进行了深度的读写集成,可运行在现有的存储平台(S3、HDFS、Azure)之上,并且完全兼容Apache Spark API。特别地它提供了如下特性:

  • (1) Spark上的ACID事务:可序列化的隔离级别确保用户读取数据时永远不会看到不一致的数据。Delta Lake允许在现有的数据湖之上添加事务层。既然在它之上有了事务,就可以确保拥有可靠、高质量的数据,并且可以对其进行各种计算。
  • (2) 可扩展的元数据处理:利用Spark的分布式处理能力,轻松处理具有数十亿个文件的PB级规模的表的所有元数据。
  • (3) 流和批处理的统一:Delta Lake中的一个表是一个批处理表,同时也是一个流源和Data Sink。流数据摄入、批量历史回填、交互式查询都是开箱即用的。
  • (4) 模式演变:自动处理模式演变,以防止在摄入期间插入坏记录。
  • (5) 时间旅行:数据版本化功能,使用户能够关注特定的时间点,支持回滚、完整的历史审计跟踪和可重复的机器学习实验。
  • (6) upsert和delete:支持merge、update和delete操作,以支持复杂的使用,如change-data-capture(CDC),slowly-changing-dimension(SCD)操作、流更新,等等。

Apache Iceberg

Apache Iceberg最初由Netflix发布,旨在解决在S3上存储大型Hive-Partitioned数据集时出现的性能、可伸缩性和可管理性挑战。

Apache Iceberg是一种用于大型分析数据集的开放表格格式。Iceberg向Presto和Spark添加了使用高性能格式的表,其工作方式与SQL表类似。Iceberg的重点是避免不愉快的意外,帮助模式演化和避免无意的数据删除,用户不需要了解分区就可以获得快速查询。

Apache Iceberg具有以下特性:

  • (1) 模式演化支持添加、删除、更新或重命名,并且没有副作用。
  • (2) 隐藏分区可以防止用户错误导致不正确的结果或非常慢的查询。
  • (3) 分区布局演化可以在数据卷或查询模式更改时更新表的布局。
  • (4) 时间旅行支持使用完全相同的表快照的可重复查询,或者让用户轻松地检查更改。
  • (5) 版本回滚允许用户通过将表重新设置为良好状态来快速纠正问题。

Apache Iceberg支持Apache Spark的读和写,包括Spark的结构化流。Trino (PrestoSQL)也支持读取,但对删除的支持有限。Apache Flink支持读写。最后,Iceberg为Apache Hive提供读取支持。

Apache Iceberg的优势在于包含大量分区的表的读性能。通过维护将对象映射到分区的清单文件并保持列级统计信息,Iceberg避免了昂贵的对象存储目录清单或从Hive获取分区数据的需要。

此外,Iceberg的清单允许将单个文件同时分配给多个分区。这使得Iceberg表在分区修剪方面非常高效,并改善了高选择性查询的延迟。

Apache Hudi

同样重要的还有Apache Hudi(发音为hoodie)。它比Iceberg或Delta Lake更面向流,更像一个额外的处理层,而不仅仅是数据湖中使用的表格格式。Hudi的主要特点是引入增量架构。

Hudi最初由Uber开源,旨在支持柱状数据格式的增量更新。它支持从多个来源获取数据,主要是Apache Spark和Apache Flink。它还提供了一个基于Spark的实用程序来读取外部资源,比如Apache Kafka。

支持从Apache Hive、Apache Impala和PrestoDB中读取数据。还有一个专门的工具来同步Hudi表模式到Hive Metastore。

Apache Hive

Apache Hive数据仓库软件已经出现一段时间了。随着新的挑战的出现,Hive现在正试图解决一致性和可用性问题。它方便了使用SQL读取、写入和管理分布存储中的大型数据集。结构可以投射到存储中已经存在的数据上。使用ACID语义的事务已经被添加到Hive中,以解决以下应用场景:

  • (1) 数据流摄取:使用Apache Flume、Apache Storm或Apache Kafka等工具将数据流传输到Hadoop集群中。虽然这些工具可以以每秒数百行或更多行的速度写入数据,但Hive只能每15分钟到1小时添加一次分区。而添加分区通常会很快导致表中分区数量过多。这些工具也可以将数据流传输到现有的分区中,但这会导致读取器进行脏读(即,在开始查询之后会看到写入的数据),并在目录中留下许多小文件,从而对NameNode造成压力。Hive现在支持这样的场景,即允许读取器获得一致的数据视图,并避免过多的文件。
  • (2) 缓慢变化的维度(SCD):在典型的星型模式数据仓库中,维度表会随着时间缓慢变化。这些变化导致插入单个记录或更新记录(取决于所选择的策略)。Hive从0.14开始就能够支持这一功能。
  • (3) 数据重申:有时收集的数据被发现是不正确的,需要纠正。从Hive 0.14开始,可以通过INSERT、UPDATE和DELETE来支持这些用例。
  • (4) 使用SQL MERGE语句进行批量更新。

对比

在构建数据湖时,可能没有比存储数据的格式更重要的决策了。其结果将对其性能、可用性和兼容性产生直接影响。Delta Lake、Iceberg和Hive的对比见下表。

平台 支持的分析工具 文件格式 回滚 压缩和清理 时间旅行
Delta Lake Apache Spark Parquet 支持 支持,手动处理 支持
Apache Iceberg Apache Spark, Presto Parquet, ORC 支持 不支持 支持
Apache Hive Hive, Apache Spark ORC 不支持 手动 & 自动处理 不支持

随着Apache Hudi、Delta Lake和Apache Iceberg等项目的成熟,表格式逐渐在大数据领域占据了主导地位,并打破了世界上大多数公司都在使用的经过验证的传统数据湖技术。


《Spark原理深入与编程实战》