有效区分大文件的算法

时间:2010-01-08 19:45:40

标签: algorithm diff rcs

我必须存储两个非常大的文件A和B(如100GB)。然而,B在大部件中可能与A类似,因此我可以存储A和diff(A,B)。这个问题有两个有趣的方面:​​

  1. 文件太大,无法通过我知道的任何差异库进行分析,因为它们是内存中的
  2. 我实际上并不需要差异 - 差异通常具有插入,编辑和删除,因为它意味着人类可以阅读。我可以用更少的信息逃脱:我只需要“新的字节范围”和“从任意偏移的旧文件中复制字节”。
  3. 我目前在如何计算在这些条件下从A到B的增量时感到茫然。有谁知道这个算法?

    同样,问题很简单:编写一个算法,可以用尽可能少的字节存储文件A和B,因为两者都非常相似。

    附加信息:虽然大部件可能相同,但它们可能具有不同的偏移并且可能出现故障。最后一个事实是为什么传统的差异可能不会节省太多。

5 个答案:

答案 0 :(得分:16)

您可以使用rdiff,它可以很好地处理大文件。在这里,我创建了两个大文件AB的差异:

  1. 创建一个文件的签名,例如

    rdiff signature A sig.txt
    
  2. 使用生成的签名文件sig.txt和另一个大文件,创建增量:

    rdiff delta sig.txt B delta
    
  3. 现在delta包含BA时重新创建文件delta所需的所有信息。要重新创建B,请运行

    rdiff patch A delta B
    
  4. 在Ubuntu中,只需运行sudo apt-get install rdiff即可安装它。它非常快,我的PC每秒大约40 MB。我刚刚在8GB文件上试过它,rsync使用的内存大约是1MB。

答案 1 :(得分:13)

看看RSYNCs算法,因为它的设计非常适合这样做,因此它可以有效地复制增量。我记得,这个算法已经很好地记录了。

答案 2 :(得分:8)

这正是称为"data deduplication"的问题。最常用的方法是:

  • 读取块中的文件:
    • 拆分所谓“块”的数据。最常用的方法称为“内容定义分块使用Rabins指纹识别方法”(Code)。使用该分块方法可以在大多数数据集上实现更好的重复数据删除,然后使用静态大小的块(例如,显示为here)。
    • 使用加密指纹识别方法对组块进行指纹识别,例如, SHA-256。
    • 如果指纹已知,则将指纹存储在索引中并查找每个块。如果指纹已知,则无需再次存储块。只有当指纹未知时,才必须存储数据。

这种重复数据删除算法并不像xdelta,但对于大型数据集来说速度更快,可扩展性更高。分块和指纹识别以每个核心约50 MB / s(Java)执行。索引大小取决于冗余,块大小和数据大小。对于200 GB,它应该适合存储器以用于例如大小的块大小。 16KB。

Bentleys and Mciloys压缩方法非常相似(例如由Googles BigTable使用),但我不知道任何使用压缩技术的开箱即用命令行工具。

"fs-c"开源项目包含大部分必要的代码。但是,fs-c本身只会尝试在内存中或使用Hadoop群集来测量冗余和analzye文件。

答案 3 :(得分:6)

一个问题是文件中的记录大小是多少,即偏移量可以逐字节更改,还是文件包含1024B块。假设数据是面向字节的,您可以执行以下操作:

  1. 为文件A创建一个后缀数组。这个数组是文件A的所有索引值的排列。如果A有2 ^ 37个字节,那么索引数组最容易用64位整数表示,所以每个字节(文件的偏移量)对应于索引数组中的8个字节,因此索引数组将长2 ^ 40个字节。例如。比方说800 GB。例如,您也可以仅为每个第1024个位置编制索引,以减小索引数组的大小。这样就可以根据可复制片段的平均运行时间来确定包装质量。

  2. 现在贪婪地打包从偏头o = 0开始的文件B,然后使用索引数组找到A中与“o”开头的数据匹配的最长匹配。您在打包文件中输出该对。这样就可以在没有任何编码16字节的情况下使用,所以如果运行是<你实际上丢失了16个字节的空间这可以通过使用随后的位级编码并使用位标记来标记是否编码隔离字节(标记+ 8位= 9位)或偏移/长度对(标记+ 40位+ 40位= 81)来轻松解决比特),比方说。将最长的片段打包到o后,将o增加到片段后的下一个字节,然后重复到文件末尾。

  3. 后缀数组的构造和使用很简单,您应该很容易找到参考。在高速应用程序中,人们使用后缀树或后缀尝试,这些操作更复杂但提供更快的查找。在您的情况下,您将在二级存储上使用该阵列,如果打包阶段的运行速度不是问题,则后缀数组应该足够。

答案 4 :(得分:1)

根据您的性能要求,您可以通过对指纹块进行采样,并在匹配时增长它们。这样您就不必在整个大文件上运行校验和。

如果您需要任意字节对齐并且您真的关心性能,请查看simhash algorithm,并使用它来查找类似但未对齐的块。