iDedup,一个主存储系统的在线重删技术

FAST’12, iDedup: Latency-aware, inline data deduplication for primary storage.

二级存储是重删技术的主要应用场景,少量主存储使用了离线重删技术。二级存储要求高吞吐率,主存储要求低延迟。下图是重删技术的分类,和iDedup所处的位置。


0.介绍

主存储环境下,在线重删最大的挑战是不能增加前台操作的延迟。但是,重删元数据的管理和访问会增加写延迟;碎片导致逻辑连续读被拆分为随机IO增加读延迟;管理数据块的引用次数增加删除延迟。

iDedup尝试解决这些问题,仅仅增加了5%的CPU开销和2-4%的操作延迟,重删率达到理想情况的60-70%。

1.观察与原理

iDedup基于两点观察:
  1. 通过测试块长对重删率的影响,发现重删率的下降小于块长的增长速度,说明大多数重复数据有聚集的现象,这是空间局部性;
  2. 通过测试指纹索引表的大小对重删率的影响,判断相同的数据是否在短时间内重复写入,发现重删率的下降也小于索引表的缩小速度,证明重复数据存在时间局部性。
利用空间局部性,选择性地重删数据,只有当文件中连续的数据,它们的副本在磁盘上也连续,才进行重删。如果空间局部性确实存在,那么选择重删的重删率损失就很有限。这个数据快序列的最小长度(threshold)是一个可配置参数,可能对于不同负载,需要不同的配置。这和单纯增大块长的重删有什么不同呢?首先在重删率上应该差不多,但是大块长方案的序列长度受限于块长,而此方案受限于文件长度,所以在碎片方面,优于大块长方案。

时间局部可以用于优化索引。一些备份系统尝试过滤所有的重复数据,因此索引很大,只能放到磁盘,这在主存储系统是不允许的,因为这会引入昂贵的随机IO。如果时间局部性存在的话,就是说一个块是重复的,那么短期内很可能又会出现同样的块。因此索引被设计为一个LRU缓存,长期得不到重删的块会被移出内存。

2.体系结构



上图是iDedup原型的体系结构,最关键的部分是iDedup算法和Dedup元数据(LRU缓存)。

针对iDedup算法,有几个目标:
  1. 算法首先必须能找出连续存放的重复数据快序列。
  2. 能找出最长的数据快序列。
  3. 能最小化元数据的检索,减少CPU的负担。
  4. 算法应该可以和destage阶段的IO并行。
  5. 算法占用的内存和CPU不会影响其它的进程。
  6. 元数据必须为查找进行优化。
而元数据管理的数据结构,是支撑iDedup算法的关键,其本质是一个LRU缓存,每一个条目(entry)将一个指纹映射到一个DBN(磁盘块号)。必须尽量减少元数据需要的内存,因为空闲内存会被linux作为缓存,linux缓存减少会影响其它应用。

3.实现

系统最关键的是两个子系统:iDedup算法和元数据管理。

3.1 元数据管理

元数据管理包括四部分:
  • 重删元数据缓存。LRU缓存,以content node为单元。
  • 指纹哈系表,指纹到DBNs的映射。
  • DBN哈希表,将DBN映射到content node,用于删除操作。
  • 引用计数文件(磁盘),管理数据快的引用计数。
重删元数据缓存是一个固定大小的LRU缓存,每个条目称为content node,每个content node是一个指纹(16B)到DBN(4B)的映射。所有的content node放在实现分配的数组里,这样只需要4B的数组索引,而不是8B指针就可以引用一个content node(这体现了尽量减少内存使用的要求)。然后在数组之上建立三个索引:LRU链表,指纹哈希表,DBN哈希表。每个索引会为每个content node引入两个4B指针(双向链接),所以每个content node额外有24B的指针。

指纹哈系表,使用指纹作为键,每个bucket有一个指向冲突树(红黑树)的指针(4B),规定每个bucket最多16个元素,所以树的深度为4。冲突树解决的是不同指纹在哈希表内的冲突。当threshold大于1时,数据块会有多个副本,它们属于不同的序列,所以每个冲突树的每个结点又指向一颗重复树(红黑树)。



DBN哈希表,使用DBN作为键,和指纹哈系表很类似,但是没有重复树。当需要删除一个块时,就根据DBN找到该content node,删除之。这个的用户即使在删除时,如何快速更新缓存。

引用计数文件,文件记录了所有重删数据快的引用次数。按照DBN排序,并且每个块有一个4B的计数器。通过删除连续的数据块,引用的更新也聚集在一起。

3.2 iDedup算法


iDedup算法基于上述数据结构。分为三个阶段:
  1. 序列鉴定:找出重复数据快的连续序列。
  2. 序列裁剪:根据长度选择序列。
  3. 序列删除:序列长度超过threshold,就删除。
在序列鉴定阶段,新写入的数据块会计算指纹,在指纹哈系表中查找它们的副本,比如块B(n)和B(n+1),指纹是H(n)和H(n+1),如果指纹哈希表找不到任何一个指纹,则数据快都需要写入磁盘。如果都找到匹配指纹,由于重复树的存在,可能有多个匹配。如果只有一个匹配,那很好判断是否连续;如果两个块都存在多个匹配,这种情况需要找到所有可能的序列。使用红黑树的一个原语nsearch(x),如果存在x则返回x,如果不存在就返回下一个更大的数字;如果x已经最大就返回错误。下图是个例子,这个例子中重复树被画成了链表。


另外,必须能够高效记录、管理序列,尤其是区分已终结的序列,和还在增长的序列。用三元组表示一个序列<last FBN,size,last DBN>。比如,B(n)和B(n+1)开始了一个序列S1,检查B(n+1)和B(N+2)后,发现S1增长了,并且创建了一个新的序列S2。这时我们需要快速找到S1 并更新数据,所以需要用三元组为索引建一张哈希表。另外,为了快速判断一个序列是否结束了,维护两个列表,一个存储包含当前块的序列,另一个包含前一个块的序列。当处理完一个块后,没有出现在当前块列表的序列被认为是结束的。

在序列裁剪阶段,对于已结束的序列,根据threshold来处理。如果序列大于threshold,检查其与未结束序列(在当前block列表里)的覆盖,当未覆盖的子序列长度超过threshold,就将子序列重删,否则就为子序列分配存储。

在序列删除阶段,每个重删的数据快,文件元数据会将DBN更新到合适的FBN位置。引用计数文件的引用数会加一,这会引入IO,尝试删除长序列,可以减少开销。

4.实验

实验的目标是证明性能和重删率的tradeoff是合理的。系统有两个主要可调参数:1.最小删除序列,threshold,2.重删元数据缓存的大小。它们分别对应了空间局部性和时间局部性。实验分为五部分:1.重删率和threshold的关系;2.磁盘碎片和threshold的关系;3.读响应延迟和threshold的关系;4.CPU利用率和threshold的关系;5.系统缓存的命中率和元数据缓存大小的关系。实验选取了两个参照,1.baseline,代表文件系统没有重复数据删除;2.threshold=1,cache size=1GB(存储所有的重删元数据),代表了iDedup能获得的最大重删率,可以认为是常规的重删技术。

实验结果表明,threshold=4是比较理想的选择,重删率的损失在30-40%;测试磁盘碎片情况,使用的方法是统计磁盘io的长度,如果碎片少,磁盘io就比较长,反之,磁盘io比较短;threshold=1时,由于碎片多,与baseline相比,读延迟增加了11%;threshold=8的cpu使用最多,但是与baseline比也只增加了2-4%;元数据缓存对系统缓存的命中率影响很小。

posted on 2013-09-10 16:21  OpenNaive  阅读(1197)  评论(0编辑  收藏  举报

导航