Design Tradeoffs for Data Deduplication Performance in Backup Workloads-备份工作负载中重复数据删除性能的设计权衡

摘要

重复数据删除已成为现代备份系统中的标准组件。为了了解其每个设计选择(如预取和抽样)的基本权衡,我们将重复数据删除分解为一个大的N维参数空间。空间中的每个点都是各种参数设置,并在备份和恢复性能、内存占用和存储成本之间进行权衡。现有的和潜在的解决方案可以被认为是空间中的特定点。然后,我们提出了一个通用框架来评估空间中的各种重复数据删除解决方案。鉴于所有指标中没有一个解决方案是完美的,我们的目标是找到一些具有持续备份性能的合理解决方案,并在重复数据删除率、内存占用和恢复性能之间进行适当的权衡。我们对真实工作负载进行大量的实验对所需的权衡做出有效的设计决策提供了详细的指导。

1 引言

高效存储大量数字数据成为工业界和学术界的一大挑战。IDC 预测 2020 [3] 中数字数据将有 44 ZB,这将继续呈指数增长。最近的工作揭示了存储系统中大量重复数据的广泛存在,包括主要存储系统[27,37]、二次备份系统[36]和高性能数据中心[26]。为了支持高效的存储,重复数据删除由于其效率和可扩展性而在底层存储系统和上层应用程序之间是一种广泛部署的技术;在大规模存储系统(尤其是备份系统)中变得越来越重要。在备份系统中,重复数据删除将备份流划分为不重叠的可变大小的块,并使用加密摘要识别每个块,例如SHA-1,通常称为指纹。两个具有相同指纹的块被认为是重复的,而不需要逐个字节的比较。哈希冲突的概率远小于硬件错误[33]的概率,因此在现实世界的备份系统中被广泛接受。指纹索引将存储块的指纹映射到它们的物理地址。通过检查其指纹在索引中是否存在来识别重复块。在备份期间,重复块立即被消除以进行内联重复数据删除。指纹索引中不存在的唯一指纹的块被聚合成固定大小的容器(通常为 4 MB),它以日志结构方式管理[39]。编写由备份的指纹序列组成的文件谱,用于未来的数据恢复。关于重复数据删除的论文有很多[32]。然而,目前尚不清楚现有的解决方案如何做出他们的设计决策以及潜在的解决方案是否可以做得更好。因此,在论文的第一部分(第 2 节),我们提出了一种分类法,使用单个设计参数对现有工作进行分类,包括键值指纹预取和缓存分段抽样重写恢复等。与之前的调查[24,32]不同,我们的分类法是细粒度的,并进行了深入讨论。我们得到一个 N 维参数空间,空间中的每个点是在备份和恢复性能、内存占用和存储成本之间进行权衡。现有的解决方案被认为是特定的点。我们弄清楚现有解决方案如何选择它们的点,这使我们能够找到可能更好的解决方案。例如,稀疏索引[22]中的相似性检测和SiLo[38]中的段预取是高度互补的。尽管有一些开源重复数据删除平台,例如 dmdedup [35],但它们都不能评估我们讨论的参数空间。因此,我们论文的第二部分(第 3 节)提出了一个通用重复数据删除框架 (DeFrame) ,用于全面的重复数据删除评估。DeFrame实现了以模块化和可扩展的方式讨论的整个参数空间;这使得现有解决方案和潜在解决方案之间的比较成为可能。我们的目标是促进寻找提供持续高备份和恢复性能、低内存占用和高存储效率的解决方案。我们论文的第三部分(第 4 节)展示了我们在使用现实世界长期工作负载的大规模实验评估中发现。这些发现为根据所需的权衡做出合理的决策提供了详细的指导。例如,如果需要较高的恢复性能,则需要用重写算法以一定的存储效率损失为代价来提升恢复性能。使用重写算法,需要对指纹索引进行设计决策更改。据我们所知,这是第一个检查指纹索引和重写算法之间相互作用的工作。

2 内联重复数据删除空间

图1
图 1 描述了一个典型的重复数据删除系统。通常,我们在磁盘上有三个组件:(1)指纹索引将存储块的指纹映射到它们的物理位置。它用于识别重复的块。(2) 文件谱存储管理描述最终备份的逻辑指纹序列的文件谱。文件谱用于在恢复期间重建备份流。(3) 容器存储是一个日志结构的存储系统。虽然消除了重复的块,但唯一的块被聚合到固定大小的容器中。我们还在DRAM中有一个指纹缓存,它拥有流行的指纹来提高重复识别的效率。图 1 还显示了基本的重复数据删除过程,即 Base。在左上角,我们有三个样本备份流,对应于连续三天主数据的快照。每个备份流被分成块,4个连续的块构成一个段(一个段描述一小片数据流的块序列;我们假设一个最简单的分割方法)。每个块按以下步骤处理:(1)哈希引擎计算块的 SHA-1 摘要作为其唯一识别,即指纹。(2)查找DRAM指纹缓存中的指纹。(3) 如果我们找到一个匹配,跳转到步骤7。(4)否则,在键值存储中查找指纹。(5) 如果我们找到一个匹配,调用指纹预取过程。跳转到步骤7。(6)否则,块是唯一的。(7) 块是重复的。我们消除块并将其指纹写入文件谱存储中。跳转到步骤 1 以处理下一个块。
表1
在以下部分中,我们 (1) 提出指纹索引子空间(重复数据删除系统中的关键组件)来表征现有解决方案并找到可能更好的解决方案,以及 (2) 讨论指纹索引、重写和恢复算法之间的相互作用。表 1 列出了主要参数。

2.1 Fingerprint Index

指纹索引是大规模重复数据删除系统中公认的性能瓶颈[39]。最简单的指纹索引只是一个键值存储[33]。键是指纹,值指向块。通过检查其指纹在键值存储中的存在来识别重复块。假设每个键值对消耗 32 个字节(包括一个 20 字节的指纹、一个 8 字节的容器 ID 和 4 字节的其他元数据),并且块大小平均为 4 KB,索引 1 TB 唯一数据至少需要 8 GB 大小的键值存储。将所有指纹放在DRAM中并不是经济的。为了对存储成本进行建模,我们使用来自 Amazon.com [1] 的单位价格: 1TB Western Digital Blue 7200 RPM SATA 硬盘驱动器成本为 60 美元,Kingston HyperX Blu 8 GB 1600 MHz DDR3 DRAM 成本为 80 美元。总存储成本为 140美元,其中DRAM占比57.14%。
基于HDD的键值存储存在HDD的随机访问性能较差的问题,因为指纹本质上是完全随机的。例如,内容定义分块 (CDC) 的吞吐量在商业 CPU [11] 下约为 400 MB/s,因此 CDC 每秒产生 102,400 个块。每个块对键值存储产生查找请求,即每秒 102,400 个查找请求。所需的吞吐量明显高于HDD,即100 IOPS[14]。SSD 支持更高的吞吐量,venders 报告 [4] 差不多为 75,000 个 IOPS。然而,SSD 比 HDD 更昂贵,并且由于过度配置空间 [19] 的减少,随着时间的推移性能下降。
由于备份工作负载的增量性质,连续备份的指纹出现在相似的序列[39]中,称为局部性。为了减少键值存储的开销,现代指纹索引利用局部性去预取指纹,并利用指纹缓存在内存中保存预取的指纹。因此,指纹索引由两个子模块组成:键值存储和指纹预取/缓存模块。相反,该值指向预取单元。根据键值存储的使用,我们将指纹索引分为精确和接近精确的重复数据删除。
Exact Deduplication (ED):删除所有重复块以获得最高的重复数据删除率(重复数据删除前的数据大小除以重复数据删除后的数据大小)。
Near-exact Deduplication (ND):允许少量重复的块获得更高的备份性能和较低的内存占用。
根据指纹预取策略,我们将指纹索引分为利用逻辑和物理局部性。
Logical Locality (LL):重复数据删除前备份流的块(指纹)序列。它保存在文件谱中。
Physical Locality (PL):块的物理布局(指纹),即重复数据删除后的块序列。它保存在容器中。
图2图 2 显示了现有指纹索引的类别。根据重复数据删除和局部性的不同有四个变体,包括EDPL、EDLL、NDPL和NDLL。在下文中,我们将讨论它们的参数子空间以及如何选择合理的参数设置。

2.1.1 Exact vs. Near-exact Deduplication

精确重复数据删除和近乎精确的重复数据删除之间的主要区别在于键值存储的使用。对于精确的重复数据删除,键值存储必须索引所有存储块的指纹,因此变得太大而无法存储在DRAM中。指纹预取/缓存模块用于避免对键值存储的大量查找请求。由于备份工作负载中的强局部性,预取的指纹可能稍后访问。尽管指纹索引通常是查找密集型的(大多数块在备份工作负载中重复),但它的键值存储预计不是查找密集型的,因为指纹预取和缓存避免了大量的查找请求。然而,第 2.1.2 节中讨论的碎片问题降低了指纹预取和缓存的效率,使得键值存储随着时间的推移变得查找密集。
对于近乎精确的重复数据删除,仅采样的代表性指纹,即特征,被索引以缩小键值存储。具有高采样率(例如 128:1),键值存储足够小,可以完全存储在 DRAM 中。由于只有一小部分存储的块被索引,因此在键值存储中找不到许多重复的块。 指纹预取/缓存模块对于保持高重复数据删除率很重要。一旦找到索引的重复指纹,就会预取许多未索引的指纹以回答后续查找请求。采样方法对预取效率很重要,因此需要仔细选择,分别在第 2.1.2 节和第 2.1.3 节中讨论。
精确重复数据删除的内存占用与键值存储有关,并与存储的块的数量成正比。例如,如果我们使用Berkeley DB[2]与Bloom filter[12]配对作为键值存储,则对每个存储块需要1字节DRAM来保持Bloom过滤器的低假阳性率。假设 S 是 KB 中的平均块大小,M 是每个键的 DRAM 字节,每个 TB 存储数据的存储成本包括 DRAM 的 $( 10∗M/S ) 和 HDD 的 $60。给定 M = 1 和 S = 4,每个 TB 存储数据的存储成本为 62.5 美元(DRAM 为 4%)。在其他底层存储中,如RAID[31],DRAM的比例降低。
近精确重复数据删除的内存占用取决于采样率 R。假设每个键值对消耗 32 个字节,M 等于 32/R。每个 TB 存储数据的存储成本包括 DRAM 的 $(320/S∗R ) 和 HDD 的 $60。例如,如果 R = 128 和 S = 4,则近精确重复数据删除中每个 TB 数据的存储成本为 60.625 美元(DRAM 为 1%)。然而,简单地声称近乎精确的重复数据删除可以节省金钱是不公平的,因为它存储的数据包括重复的块。假设重复数据删除率损失 10%,接近精确重复数据删除中的 1 TB 数据仅在精确重复数据删除中存储 90% 的 1 TB 数据。因此,近乎精确的重复数据删除需要 1.11 TB 将 1 TB 数据存储在精确重复数据删除中。近精确重复数据删除的总存储成本约为 67.36 美元,高于精确重复数据删除。为了减少存储成本,近乎精确的重复数据删除必须实现高重复数据删除率,不小于在精确重复数据删除中重复数据删除率的 (320/S∗R + 60)/(10/S + 60)。在我们的成本模型中,近乎精确的重复数据删除需要达到精确重复数据删除97%的重复数据删除率,基于我们在第4.7节中的观察结果发现这很难。因此,近乎精确的重复数据删除通常表明成本增加。

2.1.2 Exploiting Physical Locality

备份的唯一块(指纹)被聚合到容器中。由于备份工作负载的增量性质,容器中的指纹可能在随后的备份[39]中一起访问。容器中保留的局部性称为物理局部性。为了利用物理局部性,键值存储中的值是容器 ID,因此预取单元是一个容器。如果在键值存储中识别重复的指纹,我们得到一个容器ID,然后将容器的元数据部分(指纹的摘要)读到指纹缓存中。请注意,在键值存储中,只有唯一的指纹使用它们的容器 ID 进行更新。
尽管物理局部性是逻辑局部性的有效近似,但偏差随着时间的推移而增加。例如,旧容器对新备份有许多无用的指纹。因此,指纹预取/缓存模块的效率随着时间的推移而降低。这个问题被称为碎片化,正如最近的工作[29,21]所报道的,严重降低了恢复性能。对于 EDPL,碎片逐渐将键值存储更改为查找密集型,不断增加的查找开销会导致不可预测的备份性能。我们不知道指纹索引何时将成为老化系统的性能瓶颈。
对于 NDPL,抽样方法对重复数据删除率有显着影响。我们观察到两种抽样方法,均匀抽样随机抽样。前者为每个容器中的每个R指纹选择第一个指纹,而后者选择容器中mod R = 0的指纹。尽管Sampled Index [18] 使用随机抽样,但我们观察到均匀采样更好。在随机抽样中,在写入新容器后,未对遗漏的重复指纹进行采样(mod R≠ 0),使新容器的特征更少,因此预取的概率更小。均匀采样没有这个问题实现了显著更高的重复数据删除率。

2.1.3 Exploiting Logical Locality

为了利用文件谱中保留的逻辑局部性,每个文件谱都被划分为称为段的子序列。一个段描述了备份的指纹子序列,并将其指纹映射到容器ID。我们通过唯一的 ID 识别每个段。键值存储中的值指向段而不是容器,段成为预取单元。由于段中保留的局部性,预取的指纹可能稍后访问。请注意,除了独特的指纹外,重复的指纹还具有新的段 ID(与物理局部性不同)。
对于键值存储不在DRAM中的精确重复数据删除,有必要尽可能不频繁地访问键值存储。由于图 1 中描述的基本过程遵循这一原则(仅在键值存储中检查丢失的缓存指纹),因此它适用于 EDLL。EDLL 中的问题是经常更新键值存储,因为唯一和重复的指纹都有新的段 ID。因此,所有指纹都在键值存储中使用它们的新段 ID 进行更新。在以前的研究中尚未讨论的极高的更新开销,要么快速磨损基于 SSD 的键值存储,要么耗尽 HDD 带宽。我们建议对片段中的特征进行抽样,并且只更新键值存储中唯一指纹和特征的段 ID。理论上,抽样会增加查找开销,因为它会留下许多指纹以及旧的段 ID,从而导致次优预取效率。然而,基于我们在第 4.3 节中的观察,查找开销的增加可以忽略不计,使其成为合理的权衡。采样优化的一个问题是,当用户删除一些备份后,指向陈旧段的指纹可能变得不可达。它将减少重复数据删除率。一种可能的解决方案是在键值存储中添加一列以保持容器 ID。只有回收容器中的指纹才会在键值存储中删除。额外的存储成本可以忽略不计,因为 EDLL 在磁盘上保持键值存储。
以前关于 NDLL 的研究使用相似性检测(稍后描述)而不是基本过程 [22, 10, 38]。鉴于在相似性检测中更复杂的逻辑框架和额外的内存缓冲区,仍然需要使动机变得清晰。基于我们在第 4.5 节中的观察结果,Base 过程在源代码和数据库数据集(数据集在第 4.1 节中描述)中表现良好,但在虚拟机数据集中表现不佳。虚拟机图像的主要特征是每个图像本身包含许多重复的块,即自引用。在我们的源代码和数据库数据集中没有自引用去干扰基本过程中的预取决策。因此,在虚拟机图像等复杂数据集中,需要一种更有效的指纹预取策略。作为一种解决方案,相似性检测使用缓冲区来保存处理段,并加载最相似的存储段,以便对处理段进行重复数据删除。
表2
我们在表 2 中总结了利用逻辑局部性的现有指纹索引,并讨论了 5 维参数子空间中的相似性检测:分段、抽样、段选择、段预取和键值映射。请注意,以下分段、抽样和预取方法也适用于 Base 过程。
Segmenting method. File-Defined Segmenting (FDS) 将每个文件视为一个段 [10],该段由于文件大小的差异变化很大。Fixed-Sized Segmenting (FSS) 将固定数量的块(或大小)聚合到段 [38] 中。FSS 存在类似于 Fixed-Sized Chunking 方法的偏移内容问题,因为单个块插入/删除完全改变了段边界。内容定义分段方法(CDS)检查备份流中的指纹[22,16]。如果一个块的指纹匹配一些预定义的规则(例如,最后 10 位为零),则该块被视为段边界。CDS 是抗偏移的。
Sampling method. 计算两个相似段的相似度使用所有的指纹是不切实际的。根据Broder[13],两个随机采样的子集的相似度是两个完整集合的相似度的无偏近似。一个段被认为是一组指纹。指纹的一个子集被选为特征,因为指纹已经是随机的。如果两个段共享一些特征,则认为它们相似。有三种基本抽样方法:均匀抽样随机抽样最小抽样。第 2.1.2 节解释了均匀抽样和随机抽样方法。假定抽样率是R,最小抽样在一个段里面抽取segment length/R个指纹。由于最小指纹的分布不均匀,Aronovich等人提出选择与最小指纹[9]相邻的指纹。只有抽样的指纹在键值存储中被索引。较小的 R 为段选择提供了更多的候选者,但代价是增加了内存占用。每个段抽取一个特征的话就只有一个候选者。均匀抽样存在内容偏移问题,而随机采样和最小采样是抗移位的。
Segment selection. 在新段 S 中抽样特征后,我们在键值存储中查找特征以找到相似段的 ID。可能有很多候选者,但并非所有候选者都加载到指纹缓存中,因为过多的段读取会损害备份性能。基于相似度的选择,即 Top-k,选择 k 个最相似的片段。其过程如下:(1)一次选择与 S 共享大多数特征的最相似的一个段; (2) 在剩余的候选中消除所选片段的特征,以避免给出属于已选择片段的特征的分数; (3) 跳转到步骤 1 以选择下一个相似的片段,直到选择 k 个片段或我们从候选者中进行重复数据删除 [22]。一种更积极的选择方法是将所有相似的片段一起读取,即 Top-all。Top-all 的必要优化是将相似的片段物理聚合到 bin 中,因此单个 I/O 可以获取所有相似的片段 [10]。因此需要一个专用的 bin 存储。如果我们每段采样超过 1 个特征,相似段可能将会非常多,bin 增长很快。
图 1 说明了出现了的段有多相似。假设 A1 是段 A 的第一个版本,A2 是第二个版本,依此类推。由于增量备份数据流的特性,A3 可能与其早期版本相似,即 A1 和 A2。这种相似的片段是面向时间的。一般来说,仅读取最新版本就足够了。一个例外情况是段边界变化,如果使用固定大小的分割,这种情况经常发生。边界变化可能会移动部分段 B 来分割 A,因此 A3 有两个面向时间的相似段 A2 和 B2。需要更大的 k 来处理这些情况。在像虚拟机图像这样的数据集中,由于自引用,A 可以与其他段(例如 E)相似。这些相似的片段是面向空间的。假设 A2 和 E2 都有 8 个特征,其中 6 个是共享的。在后期对 E2 进行重复数据删除后,A2 特征的 6 个被覆盖以映射到 E2。当对 A3 进行重复数据删除时,在 A2 之前选择 E2。较大的 k 增加了读取 A2 的概率。因此,对于许多面向空间的段,需要较大的k以降低备份性能为代价准确地读取面向时间的相似段。
Segment prefetching. SiLo 利用段级局部性来预取段 [38]。假设 A3 与 A2 类似,期望下一个段 B3 与 A2 旁边的 B2 相似是合理的。幸运的是,在文件谱中B2 与A2 相邻,因此在重复数据删除 A3 时预取 A2 之后的 p-1 段。如果读取超过 1 个相似的段,则段预取可以应用于所有相似的段,只要 k * p 段不溢出指纹缓存,或者只读取最相似的段。
段预取至少有两个优点:1)减少查找开销。当对A3 进行重复数据删除时将 B2 与 A2 一起预取,避免了 接下来B3读取 B2 的额外 I/O。2)提高重复数据删除率。假设 B3 的相似性检测失败(即,由于 B2 的特征发生了变化),由 A3 引起的先前段预取,其相似性检测成功(即 A3 读取 A2,B2 一起预取),为 B3 提供了重复数据删除的机会。段预取还缓解了段边界变化引起的问题。在两个面向时间的相似段的情况下,即使 k = 1,当去重A3时A2 和 B2 也会被预取 。段预取依赖于将段存储在与 Top-all 不兼容的逻辑序列中。
Key-value mapping relationship. 键值存储将特征映射到存储段。由于特征可以属于不同的段(因此有多个逻辑位置),因此键可以映射到多个段 ID。因此,该值成为段 ID 的 FIFO 队列,其中 v 是队列大小。对于 NDLL,维护队列的性能开销较低,因为键值存储在 DRAM 中。较大的 v 以更高的内存占用为代价提供更相似的段候选。在以下情况下很有用:1)自引用很普遍。较大的 v 缓解了由面向空间的相似段引起的上述特征覆盖问题。2)损坏的主数据恢复到较早的版本,而不是最新的版本(回滚)。例如,如果 A2 有一些错误,我们回 到A1,因此 A3 源自 A1 而不是 A2。在这种情况下,A1 是重复数据删除 A3 的比 A2 更好的候选者,但是 段A1 的特征已被 段A2 覆盖。较大的 v 避免了这个问题。

2.2 Rewriting and Restore Algorithms

由于碎片降低了老化系统中的恢复性能,因此提出了重写算法,即参数空间中的一个新兴维度,以允许持续的高恢复性能[20,21,17]。它识别碎片化的重复块并将它们重写到新的容器中去。尽管近乎精确的重复数据删除以重复数据删除率换取恢复性能,但我们在第 4.6 节中的观察表明重写算法是一个更有效的权衡。但是,尚未讨论重写算法与指纹索引的相互作用。
我们主要关注两个问题。(1)重写算法如何减少 EDPL 的不断增加的查找开销?由于重写算法减少了碎片化,因此 EDPL 因其更好的物理局部性而得到改善。我们在第 4.6 节中的观察表明,通过有效的重写算法,EDPL 的查找开销随着时间的推移不再增加。然后 EDPL 维持良好的备份性能。(2)当检查最近重写的块时,指纹索引是否返回最新的容器 ID?每个重写的块都会有一个新的容器 ID。如果在该块重新循环时返回旧容器 ID,则可能会发生另一个重写。基于我们的观察,这个问题在 EDLL 中比 EDPL 更明显和显着。一个直观的解释是,由于我们的第 2.1.3 节中描述的采样优化,读取包含过时容器 ID 的旧段以进行重复数据删除。因此,EDPL 因其更高的重复数据删除率而变得优于 EDLL。
虽然重写算法决定了块放置,但在内存占用有限的情况下,一个有效的恢复算法利用放置来获得更好的恢复性能。有三种恢复算法:基本LRU缓存、前向装配区域(ASM)[21]和最优缓存(OPT)[17]。在所有这些中,容器在恢复期间用作预取单元以利用局部性。它们的主要区别在于,LRU 和 OPT 使用容器级替换,但 ASM 使用块级替换。我们在第4.6节中观察了这些算法在不同位置下的性能。如果碎片占主导地位,ASM更有效。原因是LRU和OPT 具有许多无用的块,由于它们的容器级替换,这些块在 DRAM 中不会被用来恢复。另一方面,如果有效的重写算法减少了碎片,由于物理局部性更好,并且OPT由于其准确的缓存替换而表现最佳,因此容器级替换得到改善。

3 DeFrame框架

第 2 节中讨论的 N 维参数空间提供了大量的设计选择,但据我们所知,没有平台评估这些选择。在本节中,我们将 DeFrame 表示为一个通用的块级重复数据删除框架,以促进探索替代方案。在 DeFrame 中,现有和潜在解决方案被认为是 N 维参数空间中的特定点。我们在 64 位 Linux 上使用 C 和 pthreads 实现 DeFrame。

3.1 Architecture

图3如图 3 所示,DeFrame 由第 2 节中讨论的三个子模块组成。在容器存储中,每个容器都由一个全局唯一的 ID 标识。容器是利用物理局部性的预取单元。每个容器包括一个元数据部分,该部分总结了容器中所有块的指纹。我们可以通过容器 ID 获取整个容器或仅获取其元数据部分。
文件谱存储管理所有已完成备份的文件谱。在文件谱中,相关的容器 ID 与指纹一起存储,以便在不需要查阅指纹索引的情况下恢复备份。我们在每个配方中添加段边界的一些指标,以促进读取一个段,该段是利用逻辑局部性的预取单元。每个片段都由一个全局唯一的 ID 标识。例如,ID 可以由指向文件谱的 2 字节指针、文件谱中的 4 字节偏移量和指示段中有多少块的 2 字节段大小组成。
指纹索引由键值存储和指纹预取/缓存模块组成。目前支持两种键值存储:DRAM哈希表和MySQL数据库[6]与Bloom过滤器配对。由于我们在键值存储上面实现了一个虚拟层,很容易添加新的键值存储。

3.2 备份流水线

如图 3 所示,我们将重复数据删除的工作流程分为六阶段:Chunk、Hash、Dedup、Rewrite、Filter 和 Append。(1) Chunk 阶段将备份流划分为块。我们已经实现了固定分块和内容定义分块 (CDC)。(2) Hash 阶段为每个块计算一个 SHA1 摘要作为指纹。(3) Dedup 阶段将块指纹聚合成段,并通过查阅指纹索引来识别重复块。标记重复块并获得其存储副本的容器 ID。创建的段是逻辑局部性的预取单元,以及用于物理局部性的批处理处理单元。我们已经实现了 Base、Top-k 和 Mix 程序(第一个 Top-k 然后 Base)。(4) Rewrite 阶段识别碎片化的重复块,并重写它们以提高恢复性能。它是重复数据删除率和恢复性能之间的权衡。我们实现了四种重写算法,包括CFL-SD[30]、CBR[20]、Capping[21]和HAR[17]。每个碎片化的块都被标记。(5) 过滤器阶段根据它们的标记处理块。将唯一和碎片化的块添加到容器缓冲区中。一旦容器缓冲区满,它就被推入下一阶段。更新文件谱存储和键值存储。(6) Append 阶段将完整的容器写入容器存储。
我们通过 pthreads 实现流水线化的过程以利用多核架构。为模块化分离dedup、rewrite和filter阶段:我们可以实现一种新的重写算法,而不需要修改指纹索引,反之亦然。
Segmenting and Sampling. 分段方法在dedup阶段调用,在dedup阶段调用每个段进行相似度检测,或者在Base过程的过滤阶段调用抽样方法。第 2 节中提到的所有分段和抽样方法都已实现。内容定义的分割是通过检查指纹的最后 n 位来实现的。如果所有位都为零,则认为指纹(块)是新段的开头,从而生成 2^n个块的平均段大小。为了选择内容定义段的第一个指纹作为特征,随机抽样还检查最后一个 ‌log₂ R (< n) 位。

3.3 恢复流水线

DeFrame 中的恢复管道包括三个阶段:读文件谱、读块和将块写入。(1) 阅读文件谱。为恢复打开所需的备份文件谱。指纹被读取并向下一步逐个发出。(2) 读块。每个指纹都会产生一个块读取请求。容器从容器存储中读取以满足请求。块缓存被维护在内存中保存流行的块。我们已经实现了三种恢复算法,包括基本的LRU缓存、最优缓存[17]和滚动前向装配区域[21]。给定一个由重写算法确定的块放置,一个好的恢复算法在有限的内存占用下提升恢复过程。所需的块不断 向下一阶段发出。(3) 写块。使用接收到的块,在本地文件系统中重建文件。

3.4 垃圾回收

用户删除过期备份后,块变得无效(未引用任何备份),并且必须回收。垃圾回收 (GC) 有许多可能的技术,例如参考计数 [34] 和标记扫描 [18]。扩展 DeFrame 分类法以允许比较 GC 技术超出了本文的范围;目前,DeFrame 采用 [17] 中提出的历史感知重写 (HAR) 算法和 Container-Marker 算法 (CMA)。HAR 在备份期间将碎片化的有效块重写为新容器,CMA 回收不再引用的旧容器。

4 评估

在本节中,我们评估参数空间以找到执行适当权衡的合理解决方案。

4.1 Experimental Setup

表3
我们使用三个真实世界的数据集,如表3所示。内核从网络[5]下载。它由 258 个版本的未打包的 Linux 内核源代码组成。VMDK来自Ubuntu 12.04的虚拟机。我们编译源代码,修补系统,并在虚拟机上运行HTTP服务器。VMDK 有许多自引用;它也从其更少的版本和随机更新中碎片化更少。RDB 由 Redis 数据库 [7] 快照组成。该数据库有 500 万条记录,空间中的 5 GB,平均更新率为 1%。我们禁用默认的 rdbcompression 选项。
所有数据集都通过 CDC 划分为可变大小的块。我们默认使用平均段大小为 1024 块的内容定义分段。容器大小为 4 MB,接近段的平均大小。默认的指纹缓存有1024个槽去持有预取单元,是容器或段。因此,缓存可以保存100万个指纹,这对于我们的数据集来说相对较大。

4.2 Metrics and Our Goal

我们的评估是根据如下列出的定量指标进行的。(1)重复数据删除率:原始备份数据大小除以存储数据的大小。这表明重复数据删除如何有效地消除重复项,是存储成本的重要因素。(2)内存占用:运行时DRAM消耗。由于DRAM的高单位价格和能源消耗,总是首选较低的内存占用。(3)存储成本:存储块和指纹索引的成本,包括内存占用。我们忽略存储文件谱的成本,因为它是恒定的。(4) 每个 GB 查找请求:重复数据删除 1 GB 的数据键值存储所需的查找请求数,其中大部分是随机读取。(5) 每个 GB 的更新请求:重复数据删除 1 GB 的数据键值存储所需的更新请求数。较高的查找/更新开销会降低备份性能。内存内的Bloom过滤器消除了对大多数独特指纹查找请求。(6) 恢复速度:1 除以每个 MB 恢复数据 [21] 读取的平均容器。它用于评估恢复性能,其中值越大越好。由于容器大小为 4 MB,因此 4 个单元的恢复速度转换为最大存储带宽。
几乎不可能找到在所有指标中表现最好的解决方案。我们的目标是找到一些具有以下属性的合理解决方案:(1)持续、高备份性能作为最高优先级; (2) 其余指标的合理权衡。

4.3 Exact Deduplication

图4
EDPL之前的研究[39,14]未能深入了解碎片对备份性能的影响,因为它们的数据集是短期的。图 4 显示了不断增加的查找开销。我们观察到在不同的指纹缓存大小下,在Kernel 和 RDB数据集中查找开销分别增加6.5-12.0 倍和 5.1-114.4 倍。较大的缓存无法解决碎片问题;4096 槽缓存的性能与默认的1024 槽缓存一样差。128槽缓存导致RDB查找开销增加114.4倍,这表明缓存不足会导致性能出乎意料的差。这会导致实践中的复杂性,因为难以预测需要多少内存以避免意外的性能下降。此外,即使使用较大的缓存,查找开销也会随着时间的推移而增加。
图5
在将 EDLL 与 EDPL 进行比较时,我们需要确定 EDLL 的最佳分段和采样方法。图5(a)显示了在VMDK数据集中的不同分段和抽样方法下EDLL的查找/更新开销。在 Kernel和 RDB 中观察到类似的结果。增加抽样率显示了一个有效的权衡:**显著降低的更新开销,而增加的查找开销的代价可以忽略不计。**与随机抽样配对的固定大小分段表现最差。这是因为它不能对段中的第一个指纹进行采样,这对于 Base 过程很重要。其他三个组合更有效,因为它们对第一个指纹进行采样(由于我们在第 3.2 节中的优化,随机抽样在内容定义分割中表现良好)。内容定义的分割优于固定大小的分割由于抗偏移性。图5(b)显示了不同缓存大小下VMDK的查找开销。我们没有观察到 EDLL 中查找开销的不断增加趋势。由于VMDK中面向空间的相似段,128槽缓存会导致额外的I/O(比默认1024槽多17%)。Kernel和 RDB(图中未显示)不会导致这个问题,因为它们没有自引用。
图6
图 6 在查找和更新开销方面比较了 EDPL 和 EDLL。EDLL 使用内容定义的分段和随机抽样。Kernel和VMDK数据集的结果未显示,因为它们具有与RDB数据集相似的结果。EDPL 的查找开销不断增加,但 EDLL 的查找开销要低得多且持续(平均比 EDPL 低 3.6 倍)。使用 256:1 采样率,EDLL的更新开销比EDPL提高了 1.29 倍,因为它用新的段 ID 更新采样的重复指纹。请注意,查找请求是完全随机的,更新请求可以通过日志结构的键值存储来优化顺序写入,这是一种流行的设计 [8, 23, 15]。总体而言,如果需要最高的重复数据删除率,EDLL 是一个更好的选择由于它维持着高的备份性能。
发现 (1):碎片导致 EDPL 中的查找开销不断增加,但 EDLL 实现了持续的性能。抽样优化在 EDLL 中执行有效的权衡。

4.4 Near-exact Deduplication exploiting Physical Locality

图7
NDPL 简单且易于实现。图 7(a) 显示了如何为 NDPL 选择合适的抽样方法。我们只展示了VMDK的结果,这与Kernel和RDB的结果相似。均匀抽样实现了显着高于随机抽样的重复数据删除率。原因在第 2.1.2 节中讨论了;对于随机抽样,遗漏的重复指纹没有被抽样,使得新的容器的特征更少,因此预取的概率更小。抽样率是内存占用和重复数据删除率之间的权衡:较高的抽样率表明内存占用较低,但代价是重复数据删除率降低。图 7(b) 显示 NDPL 去重率对小缓存大小惊人地一致:64 槽缓存导致重复数据删除率仅比 RDB 中的默认值减少 8%。还观察到(图中未显示)是 24-93% 的额外 I/O,它们来自预取指纹。与 EDPL 相比,NDPL 具有更好的备份性能,因为它的内存键值存储以减少重复数据删除率为代价。
发现 (2):在 NDPL 中,均匀抽样优于随机抽样。指纹缓存对重复数据删除率的影响最小。

4.5 Near-exact Deduplication exploiting Logical Locality

图8
图 8(a) 将 Base 过程(见图 1)与最简单的相似性检测 Top-1 进行比较,这有助于选择合适的抽样方法。由于其在 EDLL 中所示的优势,使用内容定义的分段。在 Base 过程中,随机抽样使用的内存比均匀抽样少实现了可比较的重复数据删除率。NDLL 在重复数据删除率方面优于 NDPL,因为 NDLL 不会受到碎片化的影响。然而,令人惊讶的是,虽然正如预期的那样,NDLL 在 Kernel 和 RDB 中做得更好,但 NDPL 在 VMDK 中更好(如图 7(b) 和 8(b) 所示)。原因是自引用在VMDK中很常见。指纹预取被第 2.1.3 节中讨论的空间导向相似片段误导。此外,在VMDK 数据集中指纹缓存包含许多重复的指纹,减少了有效的缓存大小,因此一个4096槽的缓存将重复数据删除率提高了 7.5%。NDPL 没有这个问题,因为它的预取单元(即容器)是重复数据删除后。64槽缓存导致VMDK中23%的额外I/O(图中未显示),但在Kernel和RDB中没有副作用。
在 Top-1 过程中,只读取最相似的段。最小抽样略好于随机抽样。Top-1 过程比 Base 过程差。原因是双重的,如第 2.1.3 节所述:(1)段边界变化会导致更多面向时间的相似段; (2) 自引用导致许多面向空间的相似段。
发现 (3):如果自引用很常见,则基本程序在 NDLL 中表现不佳。由于自引用和段边界变化,读取单个最相似的段是不够的。
图9
我们进一步检查了剩余的 NDLL 子空间:段选择 (s)、段预取 § 和映射关系 (v)。图 9 显示了改变三个参数对重复数据删除率的影响(由于篇幅限制,省略了查找开销)。在 X 轴上,我们有格式 (s, p, v) 的参数。s表示段选择方法,无论是 Base 还是 Top-k。p 表示预取段的数量加上所选段。我们将段预取应用于所选所有相似的段。v 表示特征所指的最大段数。使用随机抽样,采样率为 128。为方便起见,我们使用 NDLL(s, p, v) 来表示空间中的一个点。
当k > 1时,较大的v会导致更高的查找开销,因为它提供了更相似的段候选。我们观察到,在缺乏自引用的Kernel数据集中,增加 v 并不具有成本效益,因为它在不增加重复数据删除率的情况下增加了查找开销。然而,在缺乏自引用的RDB数据集中,由于RDB中的回滚,NDLL(Top-1,1,2)实现了比NDLL(Top-1,1,1)更好的重复数据删除率。较大的 v 有助于提高 VMDK 中的重复数据删除率,其中自引用很常见。例如,NDLL(Top-1,1,2) 在不增加查找开销的情况下实现了比 NDLL(Top-1,1,1) 高 1.31× 的重复数据删除率。
段预取对于增加重复数据删除率和减少查找开销是有效的。随着基本过程中参数 p 从 1 增加到 4,Kernel、RDB 和 VMDK 数据集中的重复数据删除率分别提高了 1.06 倍、1.04 和 1.39 倍,而查找开销分别降低了 3.81、3.99 倍和 3.47 倍。基本过程足以在缺乏自引用的内核和RDB中实现高重复数据删除率。鉴于其简单的逻辑框架,如果自引用很少见,则基本过程是合理的选择。然而,基本过程在VMDK中只实现了73.74%的精确重复数据删除率,其中自引用很常见。
发现 (4):如果自引用很少见,则基本程序足以实现高重复数据删除率。
在虚拟机数据集存储等更复杂的环境中,需要 Top-k 程序。较高的 k 表示更高的重复数据删除率,但代价是更高的查找开销。随着在 NDLL中k从(Top-1,1,1) 增加到 NDLL(Top-4,1,1),Kernel、RDB 和 VMDK 中的重复数据删除率分别提高了 1.17 倍、1.24 倍和 1.97 倍,但代价是增加了 1.15 倍、1.01和 1.56 倍的段读取。请注意,在所有数据集上,Top-4 在重复数据删除率方面优于 Base。不同的 k 在 Kernel 和 RDB 中的影响较小,因为它们具有较少面向空间的相似片段,因此候选者更少。段预取是对 Top-k 过程的一个很好的补充,因为它摊销了增加 k 引起的额外查找开销。NDLL(Top4,4,1) 在 Kernel、RDB 和 VMDK 中分别将 NDLL(Top-4,1,1) 的查找开销分别降低了 2.79 倍、3.97 倍和 2.07 倍。它还在VMDK中将重复数据删除率提高了1.2倍。NDLL(Top-4,4,1) 实现了精确重复数据删除的 95.83%、99.65% 和 87.20% 重复数据删除率,明显高于 NDPL。
发现 (5):如果自引用很常见,则需要相似性检测。分段预取是对 Top-k 的一个很好的补充。

4.6 Rewriting Algorithm and its Interplay

表4
碎片化在老化系统中显着降低了恢复性能。提出了重写算法来权衡重复数据删除率以恢复性能。为了激发重写算法,表 4 将近乎精确的重复数据删除与重写算法 History-Aware Rewriting 算法 (HAR) [17] 进行了比较。我们选择 HAR 是因为它在识别碎片方面的准确性。作为baseline,EDPL 具有最佳的重复数据删除率,因此恢复性能最差。NDPL 显示出其提高恢复性能的能力,但不如 HAR。以RDB为例,512:1均匀抽样率的NDPL在恢复速度方面牺牲了33.88%的重复数据删除率,只有1.18倍的改进,而HAR牺牲了27.69%去重率恢复性能得到2.8倍的改进。
图10
我们现在回答第 2.2 节中的问题:(1)重写算法在查找开销方面如何改进 EDPL。(2)指纹索引如何影响重写算法。图 10(a) 显示了 HAR 如何改进 EDPL。我们观察到 HAR 成功地停止了 EDPL 中查找开销的不断增加趋势。尽管 EDPL 仍然比 EDLL 具有更高的查找开销,但它不是很大问题,因为可预测的和持续的性能是主要关注的关注点。此外,HAR 对 EDLL 没有影响,因为 EDLL 没有利用 HAR 改进的物理局部性。周期性峰值是由于Linux内核中的主要更新,如3.1到3.2。这导致了许多新的块,减少了逻辑局部性。图 10(b) 显示了指纹索引如何影响 HAR。加上重写算法后EDPL 在所有数据集中的重复数据删除率方面优于 EDLL。如第 2.2 节所述,如果读取旧段,EDLL 可能会返回过时的容器 ID,因此最近重写的块将再次重写。总体而言,通过高效的重写算法,EDPL 是比 EDLL 更好的选择,因为它具有更高的重复数据删除率和持续性能。
发现 (6):重写算法有助于 EDPL 实现持续的备份性能。使用重写算法,EDPL 比其他索引方案具有更高的重复数据删除率。
图11
我们进一步检查了三种恢复算法:LRU缓存、前向装配区域(ASM)[21]和最佳缓存(OPT)[17]。图 11 显示了这些恢复算法在Kernel和 VMDK 中使用和不使用 HAR 的效率。由于恢复算法仅在有限的内存下很重要,因此使用的 DRAM 小于表 4,在Kernel中的恢复缓存 占32 个容器大小和在 VMDK 中占 256 个容器大小。如果没有使用重写算法,由于碎片化,EDPL 的恢复性能随着时间的推移而降低。ASM 比 LRU 和 OPT 具有更好的性能,因为它永远不会在内存中保存无用的块。如果使用 HAR,EDPL 会持续高恢复性能,因为碎片已被减少。OPT 在这种情况下是最好的,因为它高效的缓存替换。
发现(7):在没有重写的情况下,推荐前向装配区域;但是使用高效的重写算法,最佳缓存更好。

4.7 Storage Cost

如第 2 节所述,在 DRAM 中索引 1 TB 唯一块,块大小为4 KB,称为baseline,成本为 140,其中DRAM开销占比为57.14%。如果考虑到DRAM的高能耗,成本甚至更高。Kernel、RDB 和 VMDK 中的基线存储成本分别为$0.23、$3.11 和 $7.55。
表5
为了减少存储成本,我们使用 HDD 而不是 DRAM 进行精确重复数据删除,或者索引 DRAM 中的一部分指纹以进行近乎精确的重复数据删除。表 5 显示了每个数据集基线的相对存储成本。EDPL 和 EDLL 具有相同的存储成本,因为它们具有相同的重复数据删除率和键值存储。我们假设 EDPL 和 EDLL 中的键值存储是一个与 Bloom 过滤器配对的数据库,因此每个存储块的 1 字节 DRAM 用于低误报率。EDPL 和 EDLL 将高抽样率的近乎精确的重复数据删除进一步降低了DRAM成本,但代价是重复数据删除率降低。如第 2.1.1 节所述,具有 128:1 抽样率和 4 KB 块大小的近乎精确的重复数据删除需要实现精确重复数据删除的 97% 的重复数据删除率,以避免成本增加。为了评估这种权衡,我们观察到 NDPL 和 NDLL 在各种采样率下的存储成本。存储成本降低了约 1.75 倍。 DRAM 成本的比例为 2.27-2.50%。
NDPL使用均匀采样,NDLL 是参数(Top-4,4,1)。如表 5 所示,NDPL 增加了所有数据集的存储成本; NDLL 在大多数情况下增加了存储成本,除了 RDB数据集 中。
发现 (8):虽然近乎精确的重复数据删除降低了 DRAM 成本,但它不能降低总存储成本。

5 结论

在本文中,我们详细讨论了重复数据删除的参数空间,我们提出了一个名为 DeFrame 的通用框架进行评估。DeFrame可以有效地找到合理的解决方案来探索备份和恢复性能、内存占用和存储成本之间的权衡。我们的发现,来自使用三个真实世界长期工作负载的大规模评估,为重复数据删除系统做出有效的设计决策提供了详细的指导。
不可能有一个在所有指标中表现最好的解决方案,为了达到最低的存储成本,由于其最高的重复数据删除率和持续的高备份性能,首选利用逻辑局部性(EDLL)的精确重复数据删除。为了实现最低的内存占用,建议使用近乎精确的重复数据删除:要么利用简单的物理局部性 (NDPL) ,要么利用逻辑局部性 (NDLL) 以获得更好的重复数据删除率。为了实现持续的高恢复性能,利用物理局部性 (EDPL) 和重写算法的精确重复数据删除将是更好的选择。

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值