奈飞倾向于使用速度优先的快速数据压缩算法


Joey Lynch 是 Netflix 的高级软件工程师,负责云数据工程。他花费大量时间在数据库之间移动数据以及对数据进行散列/压缩。
根据他的所有经验,他写了一篇很棒的博客文章,介绍了您必须处理数据的一些常见任务,他谈到了最好的算法、最差的算法以及预期的性能差异:

作为一名主要处理数据和数据库的工程师,我花了很多时间移动数据、散列、压缩、解压缩,并且通常尝试通过 TLS 在 VM 和 blob存储之间铲起数据。我经常惊讶于有多少系统只支持执行这些操作的缓慢、低效和昂贵的方式。

以我的经验,这些糟糕的算法选择比现代替代方案慢几个数量级。事实上,使用快速算法通常是实际进行压缩/散列/加密和“嗯,我会跳过它”之间的区别。为了使用我们更多的 CPU 时间来做有用的工作,而不是融化冰盖和给程序员过长的咖啡休息时间,我们将在这篇文章中探索一些更快的替代方案。

常见的不良选择

  • gzip( zlib):一个值得信赖的主力,但也是一个非常慢的算法。在很多情况下,您的网络速度很快1 Gbps+(
  • xz( lzma):一种具有相当好的比率的算法,但压缩速度很慢,以至于在实践中唯一的潜在用例是单写多读用例。
  • snappy:作为最早的“我会用比率来换取速度”的算法之一,snappy 在当时是很好的。如今,它几乎总是优于其他选择。

如果我关心的是比率
试试 zstd:为了花费更多的压缩CPU时间以获得更好的压缩率,增加压缩级别或增加块的大小。我发现在大多数数据库工作负载中,默认级别(3)甚至是1级是写量大的数据集的好选择(越来越接近lz4),10级是读量大的数据集的好选择(在每个维度上都超过了gzip)。请注意,zstd严格地支配着gzip,因为它更快,而且得到更好的比率。

更棒的是:zstd支持训练字典,如果你有很多单独的小而集体的大的JSON数据(看着你的追踪系统),这真的可以派上用场。

如果我只关心速度
试试lz4:凭借接近内存的速度和体面的比率,这种算法几乎总是比完全不压缩更安全的选择。它有很好的语言支持,对于实时压缩/解压缩来说是特别好的,因为它是如此便宜。

如果我想把数据从这里铲到那里
试试zstd --adapt. :这个功能会随着IO条件的变化而自动调整压缩率,以便在CPU和 "保持管道畅通 "之间做出当前的最佳权衡。

例如,如果你的系统有很少的空闲CPU,但有一个快速的网络(看着你的i3en实例),zstd --adapt将自动以较低的水平进行压缩,以尽量减少总传输时间。如果你有一个缓慢的网络和额外的CPU,它将自动在一个较高的级别上进行压缩。

为什么快速的数据算法很重要?
它很重要,因为大多数系统是选择慢速选项,并使常规开发活动在现代云基础设施(快速网络)中花费更多时间。比如说。

  • 备份数据。使用gzip和sha256将1 TiB的数据备份到一个快速的blob存储(可以沉降多个GiBps),需要15个小时左右。用zstd和xxhash做则需要2.2小时。及时备份是数据系统最重要的属性之一。
  • 软件包。在默认情况下,debian的软件包要么不压缩,要么用xz压缩。在一个1G的网络上安装500 MiB的未压缩的debian软件包需要~5s,用xz压缩实际上会变慢,需要~1s+~6s=~7s,而用zstd -19压缩需要~1s+~1s=~2s。如果检查sha256,将再增加~20s,总共~30s,而如果我们用blake3检查,将增加~0.1s,总共~3s。我宁愿选择3秒而不是30秒。当你构建容器镜像、烘烤云虚拟机镜像或用配置管理(puppet/chef)启动服务器时,这一点都很重要。
  • 容器镜像。默认情况下,docker使用gzip压缩和sha256校验,这意味着要解压和校验4GiB的容器,我需要大约60s的CPU时间,而不是使用zstd和xxhash的6s(或使用blake3的6.5s)。当你的docker pull在你的应用程序的启动路径中时,这很重要。

使用好的算法的一个主要缺点是它们可能并不总是默认出现在您的语言或操作系统中。我在以下实现方面有很好的经验: