MinIO 上的透明数据压缩
在这篇博文中,我们将讨论 MinIO 中的透明数据压缩选项。我们将了解启用压缩的好处,以及如何微调 MinIO 中的设置。
介绍
大多数数据都以易于阅读的文件格式存储,以便于应用程序互操作。虽然有广泛使用的图像、视频和声音压缩格式,但大多数其他数据都存储为文本、JSON、CSV 或其他类似的基于文本的格式。
Parquet、Avro 和 ORC 等格式具有可选压缩,因此通常这些格式在存储时已经压缩。视频和图像通常也使用特定领域的算法进行压缩,这些算法提供比通用格式更好的压缩。
但是,对于自定义数据,最好将数据保存为不包含解压缩访问步骤的简单格式。我们想提供一个选项,在数据存储到磁盘之前对其进行压缩。
IO 速度的透明压缩
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 Best,有时也称为 LZ4-HC,提供接近 gzip 的压缩,但即使解压缩速度很快,压缩也不是交互式速度。
S2 提供三种压缩级别;S2 Default 是最快的,在单核使用方面可以被视为 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 构建的出色应用程序,请通过sales@minio.org.cn联系我们,加入Slack 社区,关注我们的博客,或订阅我们的时事通讯。