云原生、面向 Kubernetes 、基于微服务的架构推动了对 MinIO 等网络存储的需求。在云原生环境中,对象存储的优势很多 - 它允许独立于存储硬件对计算硬件进行弹性扩展。它使应用程序无状态,因为状态是通过网络存储的,并且通过降低操作复杂性,使应用程序能够实现比以往更高的规模。从网络对象存储系统写入和读取数据的最突出标准是 S3。MinIO 是一种完全符合 S3 标准、高性能、混合和多云就绪的对象存储解决方案。与将数据引入计算的传统方法相比,通过网络存储计算工作负载数据的模式是现代分解架构的缩影。这种方法的好处是多方面的:节省成本、可扩展性和性能。我们的一个客户,一家领先的金融集团,使用 MinIO 而不是 HDFS,节省了 60%+ 的成本性能提升。这种节省绝非非凡。在可扩展性方面,Hadoop 在处理小文件方面的低效率及其对数据局部性的需求限制了其可扩展性,而 MinIO 擅长处理从 KB 到 TB 的各种对象大小。至于性能,大多数老练的 Hadoop 管理员都知道,高性能对象存储后端已成为现代实施的默认存储架构。本文详细介绍了如何通过更改存储协议、数据迁移和性能调整,将对象存储的优势引入 Hadoop。在以下部分中,我们将介绍从 HDFS 迁移到 MinIO E
hdfs:// to s3a://
默认情况下,Hadoop 生态系统中的任何大数据平台都支持与 S3 兼容的对象存储后端。这种支持可以追溯到 2006 年,当时新兴技术嵌入了 S3 客户端实现。所有 Hadoop 相关平台都使用 hadoop-aws 模块和 aws-java-sdk-bundle 来为 S3 API 提供支持。通过指定适当的协议,应用程序可以在 HDFS 和 S3 存储后端之间无缝切换。对于 S3,协议方案为 s3a://,对于 HDFS,方案为 hdfs://。
Hadoop SDK 中的 S3 客户端实现多年来不断发展,每个协议方案都有不同的协议方案名称,例如 s3://、s3n:// 和 s3a://。目前 s3:// 表示 Amazon 的 EMR 客户端。Hadoop 生态系统中可用的最突出的 S3 客户端是 s3a://,它适用于所有其他 S3 后端。
注意:s3n:// 已失效,不再受任何主要 Hadoop 供应商支持。
迁移的第一步是将 Hadoop 用于与后端存储通信的协议从 hdfs:// 更改为 s3a://。在平台的 core-site.xml 文件中,更改以下参数 Hadoop.defaultFS 以指向 s3 后端。
|---------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------|
| <property> <name>fs.default.name</name> <value>hdfs://192.168.1.2:9000/</value> </property> | <property> <name>fs.default.name</name> <value>s3a://minio:9000/</value> </property> |
有几种方法可以迁移到 MinIOAIstore。您可以将旧数据保留在 HDFS 中供 Hadoop 访问,而新数据保存在 MinIO 中,以供 Apache Spark 等云原生应用程序访问。您可以将所有内容移动到 MinIO,以便 Hadoop 和云原生应用程序访问它。或者,您可以选择执行部分迁移。您必须为您的组织选择最好的。我将在下面介绍如何进行完整迁移,并在以后的博客文章中更深入地了解如何规划迁移。
将数据从 HDFS 迁移到 S3
可以使用名为 distcp 的 Hadoop 原生工具在不同的存储后端之间迁移数据,distcp 代表分布式复制。它需要两个参数:source 和 destination。源和目标可以是 Hadoop 支持的任何存储后端。在此示例中,为了将数据从 HDFS 移动到 s3,必须将源设置为 hdfs://192.168.1.2:9000 ,目标为 s3a://minio:9000 。
>_ # configure the source and destination
>_ export src=hdfs://192.168.1.2:9000
>_ export dest=s3a://minio:9000
>_
>_ # perform the copy
>_ Hadoop distcp $src $dest
根据数据的大小和传输速度,distcp 本身可以扩展,并且可以使用大规模并行基础设施迁移数据。映射器的数量,即复制数据的并行任务的数量,可以使用 -m 标志进行配置。一个好的经验法则是将其设置为基础设施中所有节点的可用 CPU 内核数。例如,如果您有 8 个空闲节点,每个节点有 8 个内核,则 CPU 内核的数量将为 64。
>_ # configure the number of mappers
>_ export num_cpu_cores=64
>_
>_ # perform the copy with higher parallelism for large datasets
>_ Hadoop distcp -m $num_cpu_cores $src $dest
注意:映射器的数量应对应于基础设施中的可用内核数量,而不是整个集群中的内核总数。这是为了确保其他工作负载具有可用于其操作的资源。
优化性能
Hadoop 和 MinIO 之间的数据访问模式大不相同。根据设计,对象存储系统不支持编辑。这在其实现数 PB 规模的能力中起着关键作用。其次,在对象存储系统中将数据从一个位置复制到另一个位置的成本很高,因为该操作会产生服务器端副本。某些对象存储系统并不严格一致,这可能会使 Hadoop 感到困惑,因为文件可能不会显示,或者如果最终一致,则已删除的文件可能会在列出操作期间显示。
注意:MinIO 没有一致性缺点,因为它是严格一致的。
考虑到这些因素,很容易调整您的应用程序以成为 Object Storage 原生应用程序。为了帮助加快这一旅程,已经付出了巨大的努力,那就是将 S3 提交程序引入 Hadoop。顾名思义,S3 提交程序承诺向 S3 提供一致、可靠和高性能的数据承诺。提交者更改 S3 中数据的读/写访问模式。首先,它们避免了服务器端副本,否则 Hadoop 应用程序会广泛使用服务器端副本,以允许多个 Hadoop 工作线程原子写入数据。一些提交者甚至使用本地驱动器作为缓存,并且只将最终输出写入 MinIO以提高性能。有三个提交程序,每个提交程序都有不同的权衡来处理各种用例。他们是:
-
目录提交者
-
分区 Committer
-
提交者
为了在应用程序中启用 committer,请在 core-site.xml 文件中设置以下配置:
<property>
<name>mapreduce.outputcommitter.factory.scheme.s3a</name>
<value>org.apache.Hadoop.fs.s3a.commit.S3ACommitterFactory</value>
<description>
The committer factory to use when writing data to S3A filesystems.
</description>
</property>
目录提交者
此提交程序首先更改访问模式以在本地 (缓存驱动器) 写入数据,一旦收集到要写入的数据的最终版本,就会执行写入。这种编写风格更适合分布式计算和 MinIO通过快速网络连接,并通过防止服务器端副本大大提高性能。要选择此提交程序,请将以下参数 fs.s3a.committer.name 设置为 directory。
<property>
<name>fs.s3a.committer.name</name>
<value>directory</value>
</property>
分区 Committer
此提交程序类似于目录提交程序,不同之处在于它处理冲突的方式。目录提交程序通过考虑整个目录结构来处理写入同一文件的不同 Hadoop 工作程序的冲突。对于分区的提交程序,冲突是逐个分区处理的。如果目录结构是深度嵌套的或通常非常大,则与目录提交程序相比,此提交程序提供更高的性能。仅建议将其用于 Apache Spark 工作负载。
<property>
<name>fs.s3a.committer.name</name>
<value>partitioned</value>
</property>
Magic 提交者
这个 committer 的内部工作原理不太为人所知,因此命名为 Magic committer。它会自动选择最佳策略以实现尽可能高的性能。它仅适用于严格一致的 S3 存储。由于 MinIO 是严格一致的,因此可以安全地使用 Magic committer。建议在您的工作负载中尝试此提交程序,以将性能与其他提交程序进行比较。
<property>
<name>fs.s3a.committer.name</name>
<value>magic</value>
</property>
选择 Committer 的一个好的经验法则是从最简单且最可预测的目录 Committer 开始,如果您的应用程序需求不能得到满足,请尝试其他两个 Committer(如果适用)。一旦选择了合适的提交者,您的应用程序就可以接受性能和正确性的测试。