MinIO 上的透明数据压缩
在这篇博文中,我们将讨论 MinIO 中的透明数据压缩选项。我们将探讨启用压缩的优势以及如何在 MinIO 中微调设置。
介绍
大多数数据存储在易于读取的文件格式中,以便应用程序之间轻松互操作。虽然图像、视频和声音压缩有广泛使用的格式,但大多数其他数据存储为文本、JSON、CSV 或其他类似的基于文本的格式。
像 Parquet、Avro 和 ORC 这样的格式具有可选的压缩,因此这些格式在存储时通常已经压缩了。视频和图像通常也使用特定领域的算法进行压缩,这些算法比通用格式提供更好的压缩效果。
但是,对于自定义数据,最好将数据保留在简单的格式中,该格式不包含访问数据的解压缩步骤。我们希望提供一个选项,在将这些数据存储到磁盘之前对其进行压缩。
I/O 速度下的透明压缩
MinIO 的压缩旨在实现透明压缩,而不影响系统的整体性能。
MinIO 使用基于 Snappy 的压缩方法,称为 S2。它与 Snappy 内容兼容,但具有 两个格式扩展。首先,它允许比 Snappy 流允许的 64KB 块更大的块。这极大地提高了压缩率。其次,它添加了“重复偏移量”,这主要为机器生成的数据(如日志文件、JSON 和 CSV)提供了压缩改进。它还允许有效地对超过 64 字节的匹配项进行编码,这是 Snappy 的一个痛点。
S2 还允许在输入速度超过单个核心吸收速度的情况下对多个块进行并发压缩。这对于保持单个请求的响应能力很重要。实际上,使用 16 个或更多个核心的限制将是内存速度。
压缩率
一些设备供应商会在计算每 TB 成本时承诺或甚至假设一定的压缩率。对于压缩,没有保证的比率高于 1:1。不同的数据类型会产生不同的压缩率,我们认为没有有意义的方法提供任何平均压缩率。压缩率永远不应在真空中进行评估——它们应该始终与压缩速度配对,因为实际压缩是这两个因素的权衡。
让我们比较一个数据类型来观察差异。我们在 AMD64 平台上比较了这些算法的 Go 实现,最多使用 16 个核心。
首先,横轴是截断的压缩率,即从未压缩大小实现的减小。右边更好。为了参考,已经包含了单线程 gzip 级别 5。
解压缩速度使用单个核心,即使 S2 提供并发解压缩。
对于此数据,Snappy 大约比 Gzip 参考低 10%。由于我们正在处理减少百分比,这也意味着 Snappy 占据了 Gzip 压缩数据的约 1.6 倍的空间。这忽略了 Snappy 解压缩速度比 Gzip 快约 4 倍的事实。
LZ4 通常被认为优于 Snappy。允许多个核心进行压缩的 LZ4 实现也使这一点更加清晰。但是基础压缩更好。LZ4 最佳,有时也称为 LZ4-HC,提供的压缩接近 gzip,但即使解压缩速度很快,压缩速度也不在交互式速度范围内。
S2 提供三个压缩级别;S2 默认是最快的,可以被视为 Snappy 在单核心使用方面的直接竞争对手。对于这种数据类型,它在任何 LZ4 级别上都表现出色,并且具有明显更高的吞吐量。此模式由 MinIO 用于没有汇编实现的平台。
S2 Better 允许以牺牲一点 CPU 为代价换取更高的压缩率。这里的压缩与 Gzip 相媲美,但解压缩速度要快得多。此模式由 MinIO 在有汇编的平台上使用——目前是 AMD64。
S2 Best 是 S2 使用当前格式所能达到的最佳压缩。这可以在压缩速度/资源不是最重要的,但仍然需要快速解压缩的情况下使用。目前 MinIO 不使用此模式,但可能会将其作为生命周期选项实现,用于一段时间内未更改的对象。
为了比较,这里有一些其他数据类型的比较
不可压缩对象
现代压缩的一个重要特征是它对预压缩数据表现良好。传统上,预压缩数据一直是压缩算法的一个问题。压缩器在遇到不可压缩数据时通常会慢得无法接受。
因此,许多人本能地知道重新压缩已经压缩的数据是不好的。但是,许多现代实现现在能够在一定程度上快速跳过不可压缩的部分。
对于上面的压缩器,这些是在 2GiB (2,147,483,647 字节) 不可压缩数据上的速度
在这里,我们还包括了来自 Go 标准库的 gzip,作为这种“糟糕”行为的代表。另一种 gzip 实现没有显示此问题。在所有其他情况下,内容处理得相当快,并且它们通过了测试。
这意味着 MinIO 可以预期很好地处理预压缩数据。
搜索压缩文件
压缩的典型缺点是失去了在文件中跳过的能力。解决此问题的方法是独立地压缩块,并保留一个索引,将一定数量的未压缩偏移量映射到压缩偏移量,解压缩可以在该偏移量开始。
压缩独立块会稍微降低压缩率,但使用更大的块会降低得更少。Snappy/S2 默认情况下将流压缩为独立块。
对于 MinIO,这一点很重要,因为 S3 GetObject 请求可以包含可选的范围以检索。这允许检索对象的各个部分,我们希望尽可能高效地进行检索。
从 RELEASE.2022-07-13T23-29-44Z 开始,我们现在为上传的每个大于 8MB 的文件部分生成一个索引。然后,该索引在内部附加到元数据。这使我们能够有效地向前跳过,并且只解码返回请求数据所需的对象部分。
该索引通常为 16 字节 + 每个 MB 数据大约 3 字节。这使 MinIO 能够与检索第一个字节一样快的速度服务压缩文件中的任何字节。
压缩 + 静态加密
默认情况下,需要一个额外的参数才能让 MinIO 将要加密到磁盘上的数据进行压缩。这是为了确保您了解此操作的影响。
当压缩数据时,您会得到两个数字;未压缩大小和压缩大小。如果没有压缩,任何获取您数据的人只能看到其中一个——未压缩大小。
虽然这仍然不能让您访问压缩文件中的任何数据,但它确实提供了一些关于数据的提示。它可以告诉你一些它不可能包含的数据类型。如果您看到一个压缩了 50% 的文件,那么它极不可能包含 MP4 压缩视频。
同样,压缩到只有几个字节的文件很可能包含一个非常简单的重复序列。无法确定序列是什么,但它减少了可能性。从 RELEASE.2022-07-13T23-29-44Z 开始的 MinIO 将压缩输出填充到 256 字节的倍数。此填充不会记录在任何地方。我们不认为这是对这个问题的完全解决方法,但它极大地降低了泄露的大小信息对对手的有用性。
这是 MinIO 不向客户端返回有关压缩大小的任何信息的主要原因。因此,任何关于此的信息都需要访问后端存储或后端网络通信。
有了这些信息,您现在拥有足够的知识来确定您是否认为启用压缩和加密是安全的。
CRIME 攻击在 MinIO 上是不可行的,因为我们不允许修改或追加任何压缩流。我们也不对对象版本进行重复数据删除/压缩,因为这会泄露太多关于文件的信息。
在 MinIO 中配置压缩
默认情况下,MinIO 中的磁盘压缩是禁用的。磁盘压缩可以随时启用或禁用。要启用磁盘压缩,请使用 mc admin config set myminio compression enable=on
。
这将为预设数量的扩展名和 MIME 类型启用压缩。默认情况下,这些将包括
您可以使用 mc admin config get myminio compression
检查当前设置。
您可以随时通过修改来修改此列表
mc admin config set myminio compression \
extensions=.txt,.log,.csv,.json,.tar,.xml,.bin \
mime_types=text/*,application/json,application/xml,binary/octet-stream
默认情况下,MinIO 强制排除常见的不可压缩数据扩展名,例如 gzip、音频、视频、图像文件。
可以通过将扩展名列表和 MIME 类型设置为空来为所有对象启用压缩,除了被排除的对象
mc admin config set myminio compression enable=on extensions= mime_types=
最终设置是 allow_encryption=on
,它允许即使对于将被加密的对象也能进行压缩。只有在您阅读了上面的部分并了解了其含义后才能设置此选项。
结论
MinIO 提供了业界领先的压缩方案,允许对磁盘上的数据进行完全透明的压缩。这在许多情况下可以简化压缩的启用,从而降低存储成本。
当启用压缩时,GET 和 PUT 性能在所有情况下都应该保持接近相同。实际上,在性能受磁盘读取速度限制的情况下,压缩可能会提供额外的性能,因为需要读取的数据更少。
我们将继续添加新功能。我们目前正在评估桶/前缀级别配置选项以及压缩-通过-生命周期,它将压缩达到特定年龄的文件。
如果您对这些功能感兴趣,请下载 MinIO 并亲自尝试。如果您有任何问题或想告诉我们您使用 MinIO 构建的出色应用程序,请在 hello@min.io 上联系我们,加入 Slack 社区,关注我们的 博客,或订阅我们的时事通讯。