赞
踩
当我们进行数据传输或者数据存储等场景的时候,如果数据量比较大的话,那么操作就会随着数据量的变大而变得缓慢以及耗费资源。如果是数据传输,那么大的数据量在进行网络传输的时候会非常耗时;如果是进行数据的持久化,存储到数据库,那么也会非常耗费存储空间。
对于大数据而言,最直接的优化方式,就是对数据进行一个压缩操作处理,减少数据尺寸。时长为了节省存储资源以及操作传输加速,会对数据进行压缩加工,减少它的尺寸,从而提高各项效率。
压缩类别:压缩可以分为有损压缩和无损压缩。有损压缩算法通过移除在保真情形下需要大量的数据去存储的小细节,从而使文件变小。在有损压缩里,因某些必要数据的移除,恢复原文件是不可能的。有损压缩主要用来存储图像和音频文件,同时通过移除数据可以达到一个比较高的压缩率。无损压缩,也使文件变小,但对应的解压缩功能可以精确的恢复原文件,不丢失任何数据。
时下互联网内比较流行的无损压缩算法有Gzip、Snappy、LZ4以及ZSTD等,前几种提到的压缩算法在消息中间件Kafka中都提供了使用,可以结合具体工具进行探索使用。
场景选择:不同的场景选择不同的压缩方式,肯定没有一个一劳永逸的方法,如果选择高压缩比,那么对于cpu的性能要求要高,同时压缩、解压时间耗费也多;选择压缩比低的,对于磁盘io、网络io的时间要多,空间占据要多;对于支持分割的,可以实现并行处理。
本文主要介绍这四种无损压缩算法的基础原理以及它们各自的优缺点和适合场景,并且通过具体的业务场景进行性能对比,以此来实际的深刻理解几种压缩算法。
Gzip是一个比较大众通用的压缩算法,凭借其可观的压缩比例而被大家所熟知。Gzip全名是Gnu zip,最开始是为了Unix系统文件压缩而设计开发的,如今它的方法逻辑应用到互联网的各个方面,包括http传输压缩、nginx压缩功能以及在java中提供的gzip压缩API使用等。
Gzip压缩原理是以Deflate压缩算法为基础,而Deflate算法是LZ77压缩算法的优化和Huffman编码的一个结合使用,因此我们下面会简单介绍下基础的LZ77压缩算法和Huffman编码的原理,从而深刻理解Gzip的压缩原理。
LZ77压缩算法是由Jacob Ziv 和 Abraham Lempel 于1977年提出,以此得名。
LZ77术语相关:
为了编码待编码区, 编码器在滑动窗口的搜索缓冲区查找直到找到匹配的字符串。匹配字符串的开始字符串与待编码缓冲区的距离称为“偏移值”,匹配字符串的长度称为“匹配长度”。编码器在编码时,会一直在搜索区中搜索,直到找到最大匹配字符串,并输出(o, l ),其中o是偏移值, l是匹配长度。然后窗口滑动l,继续开始编码。如果没有找到匹配字符串,则输出(0, 0, c),c为待编码区下一个等待编码的字符,窗口滑动“1”。
LZ77压缩逻辑示例:
搜索前,搜索区和待检区以及字符串状态,搜区区为空,待检区内进入了三个元素,如图所示
待检区检查第一个元素A,发现搜索区没有匹配项目,因此元素A按照原码记录,如下图
依次检查后面的元素B和C,发现搜索区没有与之相匹配的重复元素,因此按照源码记录
下面检查元素C,发现在搜索区有该元素,因此使用(offset,length)编码元素C,即(1,1),如图:
后面进行元素A匹配,发现匹配项,然后在继续一位元素B,即AB元素,也发现匹配,最后找到ABC在搜素区找到匹配项,因此使用(4,3)进行对ABC元素的编码,后续查找方式类似,知道遍历元素末尾
当所有元素遍历完毕之后,会得到一个新的经过编码的表示串,即:ABC(1,1)(4,3)(2,1)D,可以看出LZ77算法的中心思想就是利用数据的重复结构信息来进行数据压缩。
通过LZ77对数据进行初步的压缩之后,后续通过Huffman编码再次进行数据压缩,下面看下Huffman coding的原理。
相信很多人对Huffman这个词并不陌生,因为它是大学里面数据结构课程的一个算法内容。该算法依据元素出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫做Huffman编码(有时也称为霍夫曼编码)。
哈夫曼编码,核心逻辑是根据使用频率来最大化节省字符(编码)的存储空间。通过较大的字符串表示频率小的字符串,相应的通过较小字符串表示出现频率比较大的字符串,通过这个差值减少元素串的尺寸。
下面以元素串【emm tell me the truth】为例子,演示Huffman编码过程以及结果:
LZ4以其超高的吞吐量而出名,它的压缩和解压缩速度非常快,其底层压缩原理特使参考了LZ77算法,在其基础之上做了优化,可以粗暴的理解为是一个用16k大小哈希表储存字典并简化检索的LZ77。
在LZ77算法进行压缩时,耗时最多的部分是在字典中找到待搜索缓存中最长的匹配字符。若是字典和待搜索缓存过短,则能找到匹配的几率就会很小。所以LZ4对LZ77针对匹配算法进行了改动。
首先,LZ4算法的字典是一张哈希表。 字典的key是一个4字节的字符串,每个key只对应一个槽,槽里的value是这个字符串的位置。
LZ4没有待搜索缓存, 而是每次从输入文件读入四个字节, 然后在哈希表中查找这字符串对应的槽,下文称这个字符串为现在字符串。如果已经到最后12个字符时直接把这些字符放入输出文件。如果槽中没有赋值,那就说明这四个字节第一次出现, 将这四个字节和位置加入哈希表, 然后继续搜索。如果槽中有赋值,那就说明我们找到了一个匹配值。
下图展示了LZ4压缩的数据结构:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。