在配置“知名应用程序”时,我需要选择一个压缩算法。
此外,我的公司正在开发处理大量数据的分布式应用程序。我们一直在研究压缩数据以尝试减少网络带宽,但是我们在选择要使用的算法方面遇到了难题。有太多的选择。
我该如何在LZ4和Snappy之间做出决定?
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后看到了明显的性能提升,并在深度优化库后进一步获得了改进。