使用 Python 对数据进行压缩
之前在工作中遇到一个需求,需要在手机小程序端获取到微信小商店店铺的所有商品数据。由于当时我们没有在后台维护用户的商品数据,选择的解决方案是现场调用商品列表接口,然后缓存在 Redis 里。鉴于 Redis 的内存还是比较宝贵的,而用户的商品数据(转化为 json 格式后)又是一些比较有规律的文本数据,比较适合进行数据压缩,于是我调研了一下 Python 中的数据压缩的方案。
zip
标准库
Python 中有一个标准库zip
,常用来处理 zip 格式文件,提供的函数和方法也更适合文件操作。在这个案例中我们的数据是通过 http 接口获取的,额外进行一些文件操作有些麻烦和多余,zip
标准库并不适合这个场景。
zlib
标准库
zlib是一个常用的压缩、解压库,使用了 deflate 算法。zip
和unzip
工具背后其实用的就是zlib
。Python 内置了zlib
标准库,提供的接口也很简洁易用(zlib.compress
和zlib.decompress
)。
zlib
可以显著压缩数据规模。当然这个例子比较极端,重复了一百遍'abc',能达到 5%的压缩率。在真实场景下,zlib
大概能将原始数据压缩到 40%到 50%的大小。
zlib.compress
函数的第二个参数level
表示压缩级别,范围从 0 到 9,数值越低表示压缩速度越快但压缩率也越高(0 表示只编码而不进行压缩),默认值是-1,在 Python 中一般会使用级别 6。我们可以对比一下不同级别的速度和压缩率。
可以看到,在压缩《西游记》小说原文的场景中,级别 1 和级别 9 的压缩率从 50%提高到了 44%,但级别 1 的耗时只有级别 9 的 20%。在数据大小敏感的场景下下,1%的压缩率的提高也是很可观的。我遇到的这个场景数据是要存在 Redis 里的,并且每个店铺的数据规模有限,倾向于使用更高的压缩率的方案。
lzma
标准库
Python 标准库中的lzma
(顾名思义,使用 lzma 算法)同样可以用于数据压缩,并且有着更高的压缩率,提供的接口与zlib
也很相似。
使用 lzma 可以达到三分之一的压缩率,比级别最高的zlib
压缩率还要高十多个百分点,相对应的,压缩速度和解压速度会慢很多。
在实验中, 使用lzma
压缩和解压《西游记》的原文的时间是使用级别 9zlib
的四倍多。
考虑到微信小商店每个店铺的商品不会很多,花在压缩上的 CPU 时间并不长,还要考虑到请求商品列表接口的耗时,我最后在这个业务中选用了lzma
标准库。
zstd
zlib
和lzma
都是 Python 标准库,可以开箱即用。Pypi 上还是有一些其他的数据压缩、解压的库,在这里介绍一下zstd
。
zstd
(Zstandard)是 Facebook 推出的一个压缩算法,提供zlib
级别的实时压缩速率和更高的压缩比。标准的zstd
实现是官方的 C lib,在 Pypi 上也有同名的 Python 绑定实现。
zstd
有 22 个级别,选用压缩率最高的级别压缩效果和lzma
不相上下,压缩速度会快上一些(一般情况下不会用这么高的级别,压缩速度会快很多),但解压速度比lzma
要快十倍。在我遇到的这个场景下,解压的数据量不会太大,这一点解压速度的提升还不值得引入一个第三方库。当然遇到更合适的场景的话,zstd
库还是大有所为的。
总结
作为一个自带电池的语言,了解并活用 Python 标准库还是会很大程度上提高开发效率的。
版权声明: 本文为 InfoQ 作者【★忆先★】的原创文章。
原文链接:【http://xie.infoq.cn/article/cc51ea4411c2fb2e6fe368477】。
本文遵守【CC BY-NC-ND】协议,转载请保留原文出处及本版权声明。
评论