去重系统的recipe压缩
原文:File Recipe Compression in Data Deduplication Systems, FAST’13.
在去重系统中,需要为数据流保存一个指纹序列(recipe)用于重新构造数据流,一般来存储recipe并不是问题。但是当全备份很频繁,数据有效期很长,去重率又很高时,recipe在系统中的比重就上来。这篇文章就是解决这个问题。
文章使用了四种压缩技术,零块压缩、分页索引页内压缩和两种统计方法。
这是魏建生博士提出的方法,数据流中通常存在一些全是0的块,存储这些块和它们的指纹都是一种浪费,因此可以为它们分配更短的编码。此方法的压缩率依赖于数据集的特性。
SHA-1指纹有20个字节,提供了2^160的命名空间,但是实际的存储系统用不到这么大的空间,如果能够确定指纹集合的大致范围,就可以用更短的编码替代SHA-1。
首先指纹索引被组织成一个分页的哈希表,每个指纹根据它的前缀被映射到某个页中。然后对页中的指纹进行更短地编码,形成后缀,只需保证后缀编码在页内的唯一性降低了编码的复杂性。这样前缀加后缀就可以唯一定义一个指纹。
在指纹索引中维护指纹到编码的映射,使得备份过程中可以快速构造recipe,对于新的指纹需要分配新的后缀。为了快速恢复,在container内保存了编码到数据块的映射,这样知道编码后无需查询索引就可获得数据。
例如,在一个8TB的系统里,如果平均块长为8KB、页数为2^24个,那么平均每页为64个块。根据balls-into-bins理论(这部分我不是很确信,需要验证),几乎不可能有某个页会存储超过97个块,因此后缀的长度设为7个bit就可以了。加上前缀的24个bit,最终编码只要4个字节。随着系统规模的增长,需要更长的编码,比如256TB的系统,编码是5字节。使用4字节的编码,recipe的存储减少了80%。这个方法的优势是压缩率只和数据集大小相关,而与其它特点无关,因此是可预测的。
系统中每个指纹出现的频率是不同的,可以为出现频率高(被引用多)的指纹分配更短的编码,从而达到压缩的目的。统计得到指纹的分布模型后,不可以使用哈夫曼编码,因为指纹集实在太大了,不可能在内存创建哈夫曼树。作者采取折中的办法,考虑到系统中大多数指纹的熵约等于方法二分配的编码,没有必要再去重新编码,因此设置一个threshold,只为熵低于threshold(换句话说,出现频率高于threshold)的指纹分配一个更短的定长编码。
只有在若干次备份后才能获得统计模型,首次出现的指纹必须完整存储。一旦为某个指纹设定了编码,只要仍有recipe引用该指纹就不能取消这个编码。如果后来这个指纹的出现频率低于了threshold,就将该编码设为inactive,并且后期遇到该指纹就直接存储完整指纹,但是直到不再用recipe引用该指纹不能回收这个编码。
在实践中,作者为每个熵小于85%*log_2(NO. of chunks)的块分配一个3字节的码;需要维护一个编码到指纹的逆向映射,据估计,集合方法二后,这部分开销在8TB系统里大概是32MB。
连续的指纹之间是有因果关系的,当确定了某个指纹,下一个指纹很大概率可以推测出来。因此如果考虑一段一段的指纹序列,有机会获得更好的压缩率。然而存储这种模型本身开销非常大,作者采用了Misra-Gries算法近似地检测频繁的指纹对。为指纹索引中的每个指纹分配一个预测结构,这个结构额外存储了k个指纹及其各自的编码,它们都是下一个指纹的候选。当存储recipe时遇到一个指纹,需要判断其下一个指纹是否和它能配对,于是在它的预测结构中查找其下一个指纹,若存在,就用对应编码取代下一个指纹。因为配对的种类一般较少,因此k可以很小,编码可以很短(只要在预测结构中保持唯一)。
这篇文章应该是头一次讨论了recipe压缩问题,个人觉得这个问题出现得比较少,增量备份应该可以很好缩小recipe的规模;算法的局限于包括和很多索引的不兼容,比如DDFS,和最近热门的重写算法估计也存在兼容问题,而且只能用于数据规模确定的备份系统;文中疑似出现了不少错误,包括图4;熵方面的知识恰好在《数据压缩导论》上看到。
在去重系统中,需要为数据流保存一个指纹序列(recipe)用于重新构造数据流,一般来存储recipe并不是问题。但是当全备份很频繁,数据有效期很长,去重率又很高时,recipe在系统中的比重就上来。这篇文章就是解决这个问题。
文章使用了四种压缩技术,零块压缩、分页索引页内压缩和两种统计方法。
1.零块压缩
这是魏建生博士提出的方法,数据流中通常存在一些全是0的块,存储这些块和它们的指纹都是一种浪费,因此可以为它们分配更短的编码。此方法的压缩率依赖于数据集的特性。
2.分页索引和页内压缩
SHA-1指纹有20个字节,提供了2^160的命名空间,但是实际的存储系统用不到这么大的空间,如果能够确定指纹集合的大致范围,就可以用更短的编码替代SHA-1。
首先指纹索引被组织成一个分页的哈希表,每个指纹根据它的前缀被映射到某个页中。然后对页中的指纹进行更短地编码,形成后缀,只需保证后缀编码在页内的唯一性降低了编码的复杂性。这样前缀加后缀就可以唯一定义一个指纹。
在指纹索引中维护指纹到编码的映射,使得备份过程中可以快速构造recipe,对于新的指纹需要分配新的后缀。为了快速恢复,在container内保存了编码到数据块的映射,这样知道编码后无需查询索引就可获得数据。
例如,在一个8TB的系统里,如果平均块长为8KB、页数为2^24个,那么平均每页为64个块。根据balls-into-bins理论(这部分我不是很确信,需要验证),几乎不可能有某个页会存储超过97个块,因此后缀的长度设为7个bit就可以了。加上前缀的24个bit,最终编码只要4个字节。随着系统规模的增长,需要更长的编码,比如256TB的系统,编码是5字节。使用4字节的编码,recipe的存储减少了80%。这个方法的优势是压缩率只和数据集大小相关,而与其它特点无关,因此是可预测的。
3.统计学方法
系统中每个指纹出现的频率是不同的,可以为出现频率高(被引用多)的指纹分配更短的编码,从而达到压缩的目的。统计得到指纹的分布模型后,不可以使用哈夫曼编码,因为指纹集实在太大了,不可能在内存创建哈夫曼树。作者采取折中的办法,考虑到系统中大多数指纹的熵约等于方法二分配的编码,没有必要再去重新编码,因此设置一个threshold,只为熵低于threshold(换句话说,出现频率高于threshold)的指纹分配一个更短的定长编码。
只有在若干次备份后才能获得统计模型,首次出现的指纹必须完整存储。一旦为某个指纹设定了编码,只要仍有recipe引用该指纹就不能取消这个编码。如果后来这个指纹的出现频率低于了threshold,就将该编码设为inactive,并且后期遇到该指纹就直接存储完整指纹,但是直到不再用recipe引用该指纹不能回收这个编码。
在实践中,作者为每个熵小于85%*log_2(NO. of chunks)的块分配一个3字节的码;需要维护一个编码到指纹的逆向映射,据估计,集合方法二后,这部分开销在8TB系统里大概是32MB。
连续的指纹之间是有因果关系的,当确定了某个指纹,下一个指纹很大概率可以推测出来。因此如果考虑一段一段的指纹序列,有机会获得更好的压缩率。然而存储这种模型本身开销非常大,作者采用了Misra-Gries算法近似地检测频繁的指纹对。为指纹索引中的每个指纹分配一个预测结构,这个结构额外存储了k个指纹及其各自的编码,它们都是下一个指纹的候选。当存储recipe时遇到一个指纹,需要判断其下一个指纹是否和它能配对,于是在它的预测结构中查找其下一个指纹,若存在,就用对应编码取代下一个指纹。因为配对的种类一般较少,因此k可以很小,编码可以很短(只要在预测结构中保持唯一)。
这篇文章应该是头一次讨论了recipe压缩问题,个人觉得这个问题出现得比较少,增量备份应该可以很好缩小recipe的规模;算法的局限于包括和很多索引的不兼容,比如DDFS,和最近热门的重写算法估计也存在兼容问题,而且只能用于数据规模确定的备份系统;文中疑似出现了不少错误,包括图4;熵方面的知识恰好在《数据压缩导论》上看到。