我该如何在LZ4和Snappy压缩之间做出选择?

13

在配置“知名应用程序”时,我需要选择一个压缩算法。

此外,我的公司正在开发处理大量数据的分布式应用程序。我们一直在研究压缩数据以尝试减少网络带宽,但是我们在选择要使用的算法方面遇到了难题。有太多的选择。

我该如何在LZ4和Snappy之间做出决定?

1个回答

40
TL;DR答案始终是LZ4。
首先,让我们讨论它们的共同点。它们都是设计用于在压缩和解压缩时以“线速”(每个核心约为1 GB/s)操作的算法。主要用例是在将数据写入磁盘或网络之前应用压缩(这些通常远未达到GB/s)。压缩数据以减少IO,由于压缩算法非常快 - 比从媒介中读取/写入更快 - 所以它是透明的。
这两种算法都出现在2010年代初期,并可以被视为相对较新的算法。需要一个良好的十年时间才能让新技术得到采用,并出现在所有流行语言中优化稳定的库。
它们现在都广泛可用,并且有很好的库可用(我是在2021年撰写本文的),但几年前情况并非如此。它们都以类似的速度和类似的压缩比进行压缩(除了LZ4的解压缩速度要快得多)。
对于历史参考,还有第三种算法称为LZO,它也处于同一水平,但更古老(1996年的论文)且不常使用。
其次,让我们讨论它们的区别。虽然它们都非常快,但LZ4更快且更强大,因此应该优先使用。特别是在解压缩速度方面,LZ4快多了。

LZ算法通常非常快速,可以在恒定时间内进行解压缩,这是它们受欢迎的原因之一。LZ4就是为了充分利用这一特性并饱和CPU/内存带宽而构建的。

此外,LZ4是可调节的,压缩级别可以从1到16进行精细调整,这使得如果您有CPU资源的话,可以获得更强的压缩效果。如果所有支持LZ4的软件都能暴露出压缩级别作为设置,那将是很好的事情,但并不是所有软件都这样做。

当然,“越快越好”,但你可能会想知道这种速度真的重要吗?我们是否关心每个核心能够实现1 GB/s或2 GB/s?

答案是肯定的,因为其效果是明显的,并且在传输过程中的压缩应该跟上运行的硬件,包括NVMe SSD(750+ MB/s)和本地网络(1.25+ GB/s)。

对于客户端-服务器应用程序,服务器将接收和解压缩来自许多客户端的许多流,解压缩的成本非常快速地累加。一个实际的例子是分布式队列,比如Kafka,它必须在飞行中对数据进行解压缩/重新压缩,并适应客户端可以发送/接收的任何格式。

另一个主要应用场景是数据库,数据可以在存储到磁盘之前进行压缩。一个著名的例子是ElasticSearch,数据默认使用LZ4进行压缩(内部数据是不可变/追加方式,这与压缩和日志非常配合),当您对最近一个月的日志运行查询时,可能需要即时解压缩数TB数据(1GB/s听起来已经不那么快了 ;))

第三点,库的兼容性和可用性

最后但并非不重要的是,您需要找到一些库来支持您打算使用的任何压缩算法。

或者,如果我们谈论调整第三方应用程序/数据库,您需要查看可以配置哪些算法。

截至2021年我撰写本答案时,针对LZ4(以及snappy(和ZSTD))所有流行语言都有成熟的库可用。

如果您正在开发可能从速度提升中受益的软件,您应该使用LZ4。如果您正在寻找更强的压缩-虽然较慢-则可以尝试使用ZSTD。请忘记snappy。

唯一的例外可能是某些Java软件,它们可能支持snappy但不支持LZ4。

一点历史和软件考古

在Java软件中有一个特殊情况。Snappy已经有了更长时间的优化Java实现,尤其是由Kafka推动。你可能会看到这篇文章是因为你正在研究如何调整Kafka压缩。

Kafka早期就采用了snappy压缩,并要求所有语言的Kafka客户端都支持snappy。这促进了snappy的采用和进一步的优化。

如果你看到一些旧的比较,例如2018年CloudFlare的广泛的Kafka基准测试将snappy排在前面,原因是该文章过时了,当时LZ4没有得到同等支持/优化(CloudFlare最终无法使用lz4,因为当时并不是所有客户端都支持它)。

向现有系统中添加更多的压缩算法是一项艰巨的工作。现在应该支持LZ4(和ZSTD),但效果可能因情况而异。你可能需要升级你的集群和客户端库。你可能会发现一些客户端库不支持它。由于snappy与lz4之间的差别很小,如果两者都能正常工作,那么调整它们并不值得麻烦。

另外,如果你在多个数据中心之间运行,并且发现网络限制非常严重,那么你应该看看ZSTD,它具有更强的压缩能力(可以将网络流量减少2或3倍)。

LZ4现在已经成熟并且被广泛使用,但在2020年之前并不是这样(与Java之外的snappy也相同)。许多软件采用LZ4后看到了明显的性能提升,并在深度优化库后进一步获得了改进。


但根据这篇文章,Snappy是一个平衡的选择。 - kissLife
值得一提的是,Snappy有一个变种叫做S2,在Golang实现中比LZ4更快。 https://github.com/klauspost/compress/tree/master/s2#s2-compression - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接