使用 rsync 实做重复数据删除技术(转)

前言
很多人使用rsync这个工具软件进行日常文件备份的工作。这个用来取代rcp的远程档案复制工具使用非常有效率的算法进行档案比对、传输与复制,并且 支持远程shell (remote-shell) 和rsync服务器 (rsync daemon) 的弹性架构,让整个档案同步、备份的工作可以简单的进入排程,达到完全自动。

而随着软件版本的演进,超过一百个以上的功能选项,对于绝大部分的使用者来说可能还只是单纯使用「归档」 (-a) 和「同步删除」 (–delete) 这两个选项就满足了日常需求。不过像这样简单的设定在重复操作之下只能保有一份备份当时的全备份,却也同时让之前的备份直接被覆盖而无法参考。因此,如果 需要保留多次长周期的备份而使用相同的方法,这似乎意味着需要倍数的磁盘空间,和指定不同的归档路径才可以容纳得下多次全备份。

其实rsync早已支持「增量备份」的实做方法。透过不同的功能选项可以让每次同步备份过程中遇到的「差异」用不同方式保留下来,做到增量备份的效果。只 是在技巧上必须撰写指令稿 (script) 将整个备份流程包装起来才能达到实用的目的。因此已经有许多配合rsync的「前导程序」 (不用修改软件而达到修改软件的目的的工具软件) 被开发出来,使用整合的操作接口针对每次备份出来的档案进行版本控制,并提供类似高阶储存设备的「快照备份」 (snapshot) 呈现方式,让使用者可以任意切换到历史版本的目录当中直接找到之前备份的档案,而且重点是「不需要倍数的磁盘空间就可以容纳多次的全备份」,这似乎与「重 复数据删除技术」 (Data De-duplication) 有异曲同工之妙!

以下就针对rsync实做增量备份相关的功能选项做一个简单的说明,并介绍一个以perl语言所开发的前导程序「rsnapshot」,看看它是如何将周 期性的rsync备份模拟成文件系统的快照备份,让使用者可以用最节省的空间的方式保有多次的备份,而且可以直接存取任一版本的全备份。

rsync 的增量备份
为了方便说明,以下出现的语法是以直接在本机文件系统下操作为范例。如果需要透过rsync daemon或remote-shell模式应用在远程文件系统,则直接代换对应的语法即可。

基本同步
如果我们需要备份目录a,最基本的语法会是像这个样子:

rsync -a –delete a/ b/

这会在目的端产生一个目录b,两个目录以下的内容在同步备份之后会一模一样。-a代表归档模式,是-rlptgoD的简化写法,意味递归地进入来源端目录 a下所有的目录,将比对、复制所有的档案和目录,不仅保留时间、权限、拥有者、群组等属性,连符号链接及设备档案也一并复制。而–delete功能选项 的效果,在重复操作的时候,若目录a下有档案或目录被删除,会同步反应在目录b。这里需要注意到的地方,就是目录a后面的斜线是必要的,如果没有这个斜 线,则同步备份之后的结果就是将整个目录a备份在目录b之下,变成b/a/的效果。

增量备份
使用–backup选项在同步备份过程中可以让目的端的档案,被覆盖或删除之前先进行更名的动作以保留下来。

rsync -a –delete –backup a/ b/

使用这个功能选项在默认的情况下,如果目录a下的档案file1被更新或删除,则在下一次同步备份时,在目的端目录b会将前一次备份的那个版本先更名为 file1~保留下来,然后如果是更新档案则再储存新版本的file1,如果是删除档案则就不动作。这样的作法只能保有更新之前的版本,或之前还在的档 案。在反复同步备份操作之下,在目的端目录b对任一档案而言,顶多只能多留一份过去版本的备份,而形成诸多不同时间点不同档案的「备份的备份」散落在目录 b之下。

所以解决这个问题的方法是另外透过–backup-dir来指定目的端的档案在被覆盖或删除之前,先被复制到特定的路径之下。这样的作法相当是实做最简易的增量备份。

rsync -a –delete –backup –backup-dir=../c/ a/ b/

如果目录a的档案被更新或删除,则在下一次同步备份时,在目的端目录b的前一次备份的那个版本会先复制到目录c,然后再储存新的版本到目录b。 这与传统增量备份的概念正好相反,传统增量备份的第一份是全备份,之后的备份只留与前一次备份的差异;而rsync用–backup-dir方式进行增 量备份则是最后一次备份是全备份 (目录b) ,同时将差异记录在另外一个目录里 (目录c) 。所以透过每次备份指定不同backup dir的技巧,就可以记录每次备份当时的差异,这样不用倍数的储存空间,就可以保留多次备份当时的状态。但这里会有的问题是,在backup dir里出现的档案,是之前备份之后被修改或删除的档案,在利用上必须跟最后一次同步备份的目录做比较,才大概可以看得出来档案是被修改还是被删除。因此 这个备份方式并不一定适用在任何环境。

在这里要注意的是,若使用相对路径表示法,–backup-dir所指定的路径就必须是相对于目录b的路径。所以前面范例的目录b与目录c是在同一层。而且–backup-dir是配合–backup同时使用的功能选项。

另外一种与–backup-dir类似的功能选项是–compare-dest。这是一个独立的选项,它让来源端目录a与指定的compare dest目录c先进行比对,然后把是否覆盖、删除档案的动作反应在目录b。

rsync -a –delete –compare-dest=../c/ a/ b/

这样的作法必须是目录c与目录a之前曾先同步过,之后目录a的任何档案更新可以经由这个方式与目录c比对后再将更新的档案复制到目录b。这个用途比较适合追踪在前一次同步备份过后,有哪些档案被更动过,但不包含被删除。

所以如果需要两次完整的备份内容,可以用–copy-dest这个功能选项。

rsync -a –delete –copy-dest=../c/ a/ b/

它与–compare-dest类似,作法是目录c与目录a之前曾先同步过,之后一样是让来源端目录a与指定的copy dest目录c先进行比对,然后将没有被更动的档案直接从目录c复制到目录b,有被更动的档案从目录a复制到目录b,被删除的档案就不储存。这样的好处是 从目录c或从目录b来看都是完整的某一次备份,而且应用在不同主机之间的备份可以节省很多网络带宽,因为原本单纯同步复制一个新的目的端就必须重新传输所 有档案一次,而利用这个方式则直接在目的端主机上拿之前的备份来复制,进而提高同步的效率,而且每个目录都是备份当时的全备份,直接拿来还原也很方便。

不过这样的操作就等于备份几次就需要几倍的空间,与原来往增量备份方向去想的作法就背道而驰了。

所以在rsync版本2.5.6之后新增加–link-dest的功能选项,它把–copy-dest当中「没有更动的档案直接复制的动作」用档案的「硬式连结」 (hard link) 来取代。

rsync -a –delete –link-dest=../c/ a/ b/

所以同样的,目录a与目录c之前曾同步备份过,之后透过这个方式目录a会先与目录c进行比对,没有被更动过的档案直接在目录b利建立硬式链接到目录c的文件 案,有被更动的档案则从目录a复制到目录b,被删除的档案则不储存。这样一来同样从目录c或从目录b来看都是完整的某一次全备份,而且因为是档案的硬式连 结,所以相同版本的档案只占据同一份空间。如果反复备份多次,由于大部分的档案都是静态未被更动,那么所有需要的容量就是最早的全备份与之后每次备份的差 异量的总和而已。

其实在这个功能选项出现之前,就已经有方法可以做到相同的效果。一样是用rsync反复操作基本同步的方法 (-a –delete) ,只是在每次操作之前,先在目的端把之前备份好的目录进行一次用硬式连结的复制。

第一次备份:来源端目录a同步备份到目的端目录c。

rsync -a –delete a/ c/

在目的端之前的备份是目录c,则有两种方式可以产生用硬式链接复制出来的目录b:

cp -al c/ b/

cd c && find . -print | cpio -dpl ../b

第二次备份:来源端目录a同步备份到目的端目录b。

rsync -a –delete a/ b/

这里的cp是GNU cp,在Linux环境下是预设的复制工具,可以直接使用。cp -al会以归档的方式复制档案,但所有的档案以硬式连结来建立。可是在其他平台上若没有GNU cp,就不会有-al的选项,所以只能选择用cpio来进行复制。 当完成这个复制动作之后,两个目录下档案其实对应到相同的Inode,档案本身的连结计数 (link counter) 加一之后为二,档案对应到的实体区块只有一份,所以除了目录结构以外,不占额外的空间。 接下来之后的备份使用rsync基本的同步方式指定目的端为目录b。在这里不用担心因为是档案的硬式链接,目录b和目录c下同一档案当再次同步备份时会导 致一起被覆盖或删除,因为rsync预设的行为会先将异动的档案以另外的档名复制出来进行更新,然后再更名为原来的档名。所以不管是覆盖还是删除,都只是 对原本档案的连结计数做减一的动作,而在连结计数归零之前,也就是档案真正被删除之前,都不会更动到原本备份的那个版本。

所以不管使用哪一个版本的rsync,再搭配一些操作的技巧就可以实做出类似「重复数据删除技术」的效果。而我们不需要另外撰写script来实做这个部 分,因为已经有许多现成的工具软件可以自动化这些操作流程。以下就以rsnapshot这个软件为例子,说明这是怎么做到的。

rsnapshot
rsnapshot是一个自由软件 (free software) ,可以从官方网站 (http://www.rsnapshot.org/) 下载,或从操作系统的软件管理工具当中找到既有的port或package来进行安装。它是一个以perl语言开发的工具软件,一个远程文件系统的快照工 具 (remote filesystem snapshot utility) 。在架构上,可以用来备份本机或远程的文件系统,它在本机端是藉由rsync进行档案复制,或透过ssh建立安全的rsync远程shell与远程主机进 行文件传输,或直接与远程主机的rsync服务器联机。它是用「拉」的方式进行同步备份,也就是说,安装rsnapshot的主机就是发动备份的主机,也 是储存备份数据的主机。rsnapshot透过排程 (crontab) 周期地启动同步备份,而所有需要备份文件的远程主机都安装rsync或启动rsync服务器来等待周期的同步备份。当同步备份发生时,rsnapshot 根据设定将远程主机需要备份的目录「拉回」到本机特定的目录架构里。而这个目录架构就是仿真高阶储存设备所提供的「快照备份」 (snapshot) 的目录结构。依照不同的备份周期产生不同时间间隔的目录,而在每个目录下的档案都是备份当时的全备份。透过档案的「硬式连结」,在每次同步备份时,未曾更 动的档案直接使用之前备份的版本进行硬式连结到最新的备份目录下,也因此整体备份空间的需求就相当是一次全备份与异动档案的不同版本所占用的空间。

在配置上,需要设定rsnapshot.conf这个档案,和建立周期备份的排程 (crontab) 。

设定rsnapshot.conf非常简单,使用预设的配置文件rsnapshot.conf.default直接拿来修改就可以了。在这个档案里面的每一 个段落都有完整的说明可以参考。其中需要注意的地方是,由于rsnapshot可以在不同平台上运作,为了实做「硬式连结」来节省相同档案的使用空间,所 以必须根据所在的平台选择最适当的外部工具。如果使用的rsync版本支持–link-dest的功能选项,则可以直接设定link_dest为1代表 支持。如果不支持则就会使用GNU cp的-al的复制方式来建立硬式连结,因此可以指定GNU cp的所在路径。但如果作业环境里没有GNU cp工具而无法指定,则程序内部会额外仿真这个动作。

另外要注意的就是备份时间间隔的表示法,这是与建立周期备份排程密切相关的设定。根据需要来决定多久备份一次,换句话说就是单位时间可以保留几次备份。如果每四小时备份一次,意味着一天可以保留六次每四小时的备份;如果每天备份一次,代表着一周可以保留七次每天的备份。

在rsnapshot.conf.default里关于备份时间间隔的默认值如下:

interval        hourly  6
interval        daily   7
interval        weekly  4
#interval       monthly 3

在系统设定相对应的crontab:

0 */4 * * *         /usr/bin/rsnapshot hourly
50 23 * * *         /usr/bin/rsnapshot daily
40 23 * * 6         /usr/bin/rsnapshot weekly
#30 23 1 * *        /usr/bin/rsnapshot monthly

如果根据默认值配合相对应的排程,那么每四小时就会进行一次周期名称为hourly的备份,它会在snapshot_root所定义的路径下产生 hourly.0到hourly.5的六个目录,目录里面就存放着备份的内容。hourly.0是最新的备份,每四小时启动备份时,最旧的备份 hourly.5会先被删除,然后依序将4,3,2,1的目录尾数更名为5,4,3,2,再依照硬式连结产生的方式,如果是使用cp -al的模式,则将hourly.0复制出hourly.1后,直接用rsync基本同步的方式备份到hourly.0,如果是使用rsync –link-dest的模式,则在hourly.0更名为hourly.1后,rsync指定hourly.1为link dest然后备份到hourly.0。

其他不是排在最前面的周期名称不需要实际使用rsync进行备份,因为可以直接保留前一个周期名称的最旧的那个备份。譬如,周期名称为daily的排程在 每晚23:50进行,因为设定保留七份,所以最旧的一份也就是daily.6在备份开始的时候先被删除,然后依序将5,4,3,2,1,0的目录尾数更名 为6,5,4,3,2,1,最后再把hourly.5更名为daily.0就完成了备份。所以排程上刻意比hourly提前十分钟,抢在hourly.5 被删除之前先更名为daily.0。而同样的,weekly.0也是从daily.6更名得来。

如果使用默认值进行hourly,daily,weekly的备份排程,那么总共可以保有17份的备份。使用rsnapshot du的命令来可以观察集中在snapshot_root的这些备份空间使用的情形。

# rsnapshot du
15G     /backup/.snapshots/hourly.0/
16M     /backup/.snapshots/hourly.1/
21M     /backup/.snapshots/hourly.2/
23M     /backup/.snapshots/hourly.3/
19M     /backup/.snapshots/hourly.4/
19M     /backup/.snapshots/hourly.5/
22M     /backup/.snapshots/daily.0/
38M     /backup/.snapshots/daily.1/
31M     /backup/.snapshots/daily.2/
28M     /backup/.snapshots/daily.3/
53M     /backup/.snapshots/daily.4/
30M     /backup/.snapshots/daily.5/
38M     /backup/.snapshots/daily.6/
50M     /backup/.snapshots/weekly.0/
50M     /backup/.snapshots/weekly.1/
42M     /backup/.snapshots/weekly.2/
38M     /backup/.snapshots/weekly.3/
16G     total

这里显示的是一个真实环境一个月下来保留17份备份所需要的空间。一次全备份大约需要容量15G,如果使用传统备份方式保留相同数量的备份需要大约 255G。而rsnapshot实做硬式连结增量备份全部17份备份只用到大约16G的容量。而且每个周期名称目录下的所有档案就是备份当时的备份内容, 所以要找回某一次备份取得所有档案在时间上大约的一致性变得非常容易,因为这非常接近使用文件系统或储存设备所提供快照备份的功能,差别只是rsync执 行一回合从头到尾毕竟还是会有「时间差」,开始备份到结束的时间点会有段距离,相对于真正的快照备份技术等于是「慢速快门」,所以这样的作法适合用来备份 一般的档案,却不适合用来备份文件之间时间相依性非常高而且不断在变动的数据库或其他环境。

结语
其实真正的「重复数据删除技术」并不是像前述这样的应用,主要是配合在一个既有的备份环境,譬如是一个D2D或D2D2T的架构当中做为备份软件暂时缓冲 用的磁盘空间 (staging disk) 所使用的技术。透过储存设备可以识别出重复出现的不定长度数据区块而选择不储存的算法,让备份的image file在累积多次备份之后可以维持很高的「压缩率」。又由于多次备份的image file都是储存在磁盘上,所以还原的速度会比磁带还来得快速。而rsync使用硬式连结减少重复档案所需要的储存空间,也可以找到特定时间版本备份的档 案直接取回使用,在储存原理上与重复数据删除技术非常类似,在操作上与高阶储存设备提供的快照备份技术的应用方式非常接近。而为了解决rsync「慢速快 门」的问题,其实如果能够在来源端的文件系统使用真正的快照备份技术,让rsync直接备份快照版本的档案来取得时间点上的一致性,这样不仅仅可以备份一 般档案,还可以备份不断在变动的信件文件或数据库一直在开启中的数据文件,进而扩大使用rsync的应用范围。

(作者现任职于麟瑞科技)

参考数据
http://www.mikerubel.org/computers/rsync_snapshots/ Easy Automated Snapshot-Style Backups with Linux and Rsync

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值