将文件系统放在对象存储之上是一个糟糕的主意。以下是原因。

购买存储时,通常重点关注的是介质,但考虑访问方式可能更重要。在设计和采购基础设施时,您需要考虑存储协议,尤其是在抛弃传统存储以迁移到云原生对象存储时。但是,对象存储依赖于 S3 API 进行通信,而传统工作负载依赖于 POSIX,即可移植操作系统接口,它提供了一套 1980 年代制定的标准,以允许应用程序在 Unix 操作系统之间移植。大多数企业可能拥有运行了数十年的应用程序,这些应用程序是在 POSIX 上运行的。工程师也可能已经意识到 POSIX 的性能低下。
话虽如此,当您的传统系统只能以特定格式或来自特定来源摄取数据时,您的选择可能会受到限制,您可能别无选择,只能实现过时的协议或重写代码。例如,如果您只能从具有文件系统的本地磁盘摄取数据,而不能通过网络访问的 RESTful API 摄取数据,那么您必须首先将数据提供到磁盘上,应用程序才能使用它。但是,使用对象存储作为文件系统在性能、兼容性、数据完整性和安全性方面存在一些严重的负面影响。
让我们用一个名为 s3fs-fuse 的小型实用程序来演示这一点。此实用程序允许您将 S3 存储桶挂载为本地文件系统。它代表 S3(简单存储服务)文件系统 - FUSE(用户空间中的文件系统)。这是一个利用 FUSE(用户空间中的文件系统)接口将类似文件系统的接口呈现给 S3 的开源项目。
使用 s3fs-fuse
挂载 S3 存储桶后,您可以像操作本地文件系统一样操作存储桶。这意味着您可以在存储桶中的文件上使用常规文件操作(如读取、写入、移动等)。这听起来非常方便,我们可以说它简化了应用程序开发。但本质上,对象存储和文件系统存在根本差异,这将影响作为文件系统挂载的 s3 存储桶。
让我们花点时间从 s3fs-fuse
实用程序后退一步,讨论将对象存储视为文件系统的真正原因远非最佳。问题远大于 s3fs-fuse
,还包括其他实用程序,例如基于 Rust 的 Amazon S3 的挂载点,这是一个将本地文件系统 API 调用转换为 S3 对象 API 调用的文件客户端。第一个原因是所有这些实用程序都依赖于 POSIX 进行文件系统操作。POSIX 效率低下,它最初并非用于处理通过网络连接的大型文件。
基于 POSIX 的系统的速度随着对它们的请求(尤其是并发请求)的增加而降低。当大型组织需要存储和访问海量数据以用于深度学习、AI 和其他数据密集型用例时,POSIX 无法满足这些需求。虽然全闪存阵列使 POSIX 能够继续发挥作用,但可扩展性和 RESTful API(云的标志)就像氪石。
因此,在对象存储之上运行 POSIX 并非最佳选择。让我们来看一下其中的原因。
- 性能: POSIX FS 接口本质上是 IOPS 为中心的。它们是喋喋不休的、昂贵的,而且难以扩展。RESTful S3 API 通过将 IOPS 转换为吞吐量问题来解决这个问题。吞吐量更易于扩展,而且成本更低。这就是对象存储在海量规模下具有高性能的原因。在 S3 之上叠加 POSIX 无法扩展,因为 POSIX 对于通过 HTTP RESTful 接口执行来说过于喋喋不休。
- 语义: 由于对象操作是原子且不可变的,因此无法保证一致性正确性。这意味着在发生崩溃的情况下,您可能会丢失未提交的数据,或者在共享挂载的情况下遇到损坏问题。
- 数据完整性: 对文件的写入或任何修改都将在提交后才出现在命名空间中。这意味着跨共享挂载的并发访问将看不到修改。它不适用于共享访问。
- 访问控制: POSIX 权限和 ACL 比较原始,与 S3 API 处理身份和访问管理策略的方式不兼容。无法在 S3 API 之上安全地实现 POSIX 访问管理。
POSIX 还缺少开发人员钟爱的 S3 的大多数功能,例如对象级加密、版本控制、不可变性 - 这些在 POSIX 世界中根本没有等效项,而且没有任何东西可以转换它们。
POSIX 痛点
这些示例说明了问题及其影响。为了开始,我们将使用 此 CSV 文件,它大约为 10GB,包含 112 行。
注意:我们将假设 s3fs-fuse
已经安装,并且您已将对象存储中的某个存储桶挂载到您的文件系统中。如果没有,请按照 此处 的说明操作。
在这些示例中,我们将假设存储桶名为 test-bucket,文件名 taxi-data.csv 位于 /home/user/ 目录中,并且 s3fs-fuse bucket
挂载到 /home/user/test-bucket/。
复制操作
我们先尝试一些简单的事情,尝试使用 mc 命令将 CSV 文件复制到我们的 test-bucket 中,并记录所花费的时间
time mc cp /home/user/taxi-data.csv minio/test-bucket/taxi-data.csv
这应该不会花费太多时间,文件应该被复制到我们的存储桶中。现在让我们尝试使用 s3fs-fuse
做同样的事情
time cp /home/user/taxi-data.csv /home/user/test-bucket/taxi-data.csv
测试期间花费的时间
在我的情况下,我只能够将文件部分复制到存储桶中,并且操作失败,并出现以下错误
经过多次尝试后,它成功了
正如您所见,由于实用程序需要进行大量的 API 调用以及操作的总体开销,实用程序变得不稳定,大多数操作甚至没有完成。
Pandas 示例
我们向您展示了一个简单的 cp
示例,它可能令人信服,也可能不令人信服,因为说实话,您可能会认为 time cp
非常初级。
因此,对于需要更多经验证据的人来说,让我们编写一个 Python 代码片段来测试它。我们将使用 s3fs-fuse
和 python s3fs
包进行一个简单的 Pandas 示例,并查看性能影响
测试期间花费的时间
现在让我们尝试对 s3fs-fuse
做同样的事情
测试期间花费的时间
这些示例展示了对 S3 文件的持续读写操作。想象一下,多个客户端同时执行此操作,延迟会大幅增加。
消除开销!
如您所见,使用 POSIX 转换将对象视为文件与使用直接 API 处理对象之间的区别是天壤之别。在安全性、性能、数据完整性和兼容性方面,根本没有可比性。MinIO 提供了 SDK 来集成几乎所有流行的编程语言,并且可以在几乎所有平台上运行,例如 Kubernetes、裸机 Linux、Docker 容器等等。
MinIO 使用静态和传输过程中的加密以及 PBAC 来控制访问,并使用 纠删码 来保护数据完整性,从而 保护对象。无论您在何处运行 MinIO,您都将获得最佳性能,因为它利用底层硬件 (参见 为 MinIO 部署选择最佳硬件) 来提供最大可能的性能。我们在 32 个节点的现成 NVMe SSD 上对 MinIO 进行了 基准测试,GET 速度为 325 GiB/s (349 GB/s),PUT 速度为 165 GiB/s (177 GB/s)。
在 MinIO 和您的应用程序之间根本不需要文件系统工具!传统应用程序可能获得的任何优势都将被 POSIX 的痛苦所抵消。
如果您对在应用程序中使用 POSIX 转换有任何疑问,请务必在 Slack 上联系我们!