• rsync用于数据迁移/备份的几个细节


    上周我们的一个GitLab服务频繁出现web页面卡死问题,得重启虚拟机才可恢复,但重启之后没多久又会卡死。后来发现是虚拟机的磁盘大小超过了2T,而虚拟机管理那层的文件系统是ext3,最大单文件只能支持到2T(也不知道当初这个3T的虚拟磁盘镜像是怎么建立起来的,难道Xen不会给出警告?)。由于该机房没有可调动的磁盘了,于是只能另外找机房重新搭建一个环境,将数据迁过去。

    只同步指定的子目录

    场景:
    0) 要迁移的是gitlab里面的git库数据

    1. 要迁移的数据很多(大约2T),由于跨机房网络速度一般,我们期望先迁移部分重点用户的,但fork出来的git库是在不同的子目录下的(比如 ssmp/ssmp.git会有zhangsan/ssmp.git, lisi/ssmp.git),这些都得一并迁移过去。

    首先,像下面这样直接将ssmp, zhangsan, lisi三个目录全拷贝过去,肯定是不行的

    rsync -a ssmp/ssmp.git zhangsan/ssmp.git lisi/ssmp git@new-repo:/home/git/repositories
    

    因为不仅原来的目录结构丢了,三个ssmp.git还混到一起了。

    解决方法是用rsync的 filter 特性

    rsync -a --delete  --filter="merge /tmp/gitlabFilter" repositories/ git@new-repo:/home/git/repositories/
    

    但写这个filter内容的写法跟我们原来在tar那里习惯了的目录排除不一样,比如上面的场景写成下面这样是不能工作的:

    + ssmp/ssmp.git
    + zhangsan/ssmp.git
    + lisi/ssmp.git
    - *
    

    这是因为最后那个- *就已经把顶层的ssmp, zhangsan, lisi这几个目录排除掉了,于是ssmp下面的子目录是没法加进来的。

    对于这个问题,rsync的man page说得很清楚(只不过我看见大段的英文就有些晕头),需要写成下面这样:

    + ssmp/
    - ssmp/*
    + ssmp/ssmp.git
    + zhangsan/
    - zhangsan/*
    + zhangsan/ssmp.git
    + lisi/
    - lisi/*
    + lisis/smp.git
    - *
    

    这里还有一个详细的描述: Rsync backups: excluding directories

    linux的磁盘cache导致拷贝速度逐渐下降

    用rsync拷贝数据过程中发现一个现象:开始拷贝的时候速度很快,每秒有40MB左右,但拷贝几十分钟之后就降到10MB左右了,两边机器都没有跑什么应用,网络用netcat测也没有问题…

    然后我观察到的一个问题是两边的free命令都显示出内存占用很高,并且是buffered/cache一栏很高,因为这个缓存是可以手工释放的,就抱着试试看的想法试了一下:

    sync; echo 3 > /proc/sys/vm/drop_caches
    ssh root@new-repos 'sh -c "sync; echo 3 > /proc/sys/vm/drop_caches"'
    

    没想到速度马上恢复了!

    于是我改了脚本,每次调用一次rsync同步完一个git库及其fork,就调上面的语句将cache清掉,速度基本上不受影响。

    补充说明

    1. linux操作系统会将文件系统的内容缓存起来,以便后面用到时加速,但在数据迁移场景下,基本上没有“后面用到时”这个场景,这个缓存反而碍事(TODO: 为什么导致网络io下降)
    2. 对于本机内大量拷贝文件,有人提供了一个nocache命令(https://github.com/Feh/nocache Debian/Ubuntu已经收录了这个工具 https://packages.debian.org/search?keywords=nocache )。它的功能是临时禁用cache,用法是将要执行的命令用nocache包住,比如: nocache cp -a ~/ /mnt/backup/home-$(hostname)
      ​,但rsync会使用网络通讯,所以nocache rsync对远端没有作用( *Note however, that rsync uses sockets, so if you try a nocache rsync, only the local process will be intercepted.)
    3. 也有人在多年以前给rsync提交了一个补丁(https://bugzilla.samba.org/show_bug.cgi?id=9560 ),增加了--drop-cache选项,但遗憾的是没被接纳,说是过于linux-specific,开发人员的意见(见comment 3 )是改用nocache: nocache rsync -aiv --rsync-path='nocache rsync' some-host:/src/ /dest/. P.S. nocache工具的主页最后在acknowledgements部分 说,其实它是衍生自rsync的这个补丁的。

    参考资料:

    已经备份过的文件不再重复拷贝(从旧备份硬链接未修改过的文件)

    场景:要求每天建立一个备份。因为数据量很大,所以从备份速度、空间占用上来说,期望重复文件就不要重复拷贝了

    第一个版本是这样的:

    rm -rf backup.2
    mv backup.1 backup.2
    cp -al backup.0 backup.1
    rsync -a -l --delete source_dir backup.0
    

    在上面的脚本中,多个备份之间的硬链接是依靠cp -a -l来建立的,而新增的文件依靠rsync -a -l也可以尽量硬链接已有的文件。

    但这个脚本有点问题: 如果文件内容没变,只是文件属性(属主、修改时间、权限)发生变化的话,rsync不会重新拷贝文件,而是直接修改原文件的属性,而由于采用了硬链接,backup.1backup.2等旧备份目录里面的文件属性也发生了变化!

    解决这个问题的方法是改为:

    rm -rf backup.2
    mv backup.1 backup.2
    mv backup.0 backup.1
    rsync -a --link-dest=backup.1 source_dir backup.0
    

    注意这里的--link-dest=backup.1,它的含义是:先到backup.1这个目录找找有没有一样的文件,有的话将其硬链接到目标目录(backup.0),没有的话再拷贝。属性的变化会认为是不同的文件,会生成新拷贝。

    如果文件属性的变化对于你的场景没有场景,那么两种方法都可以用,第一种方法还能少一些拷贝文件。

    参考资料

    打包(archive)差异备份文件

    场景:比较老的备份打包后转到其它机器(或者磁带机)上,每周一次全量备份,然后每天的增量单独打包

    rsync -a --compare-dest=backup.week backup.1 backup.incremental-20150604
    cd backup.incremental-20150604
    tar zcvf ../backup.incremental-20150604.tar.gz *
    

    --compare-dest的含义跟上面--link-dest类似:先到这个参数指定的目录找找有没有想要的文件,如果没有再从源目录拷贝

  • 相关阅读:
    mysql--创建表,插入数据,修改表名,删除表,简单查询/内连接、左/右连接
    页面访问过程及get/post的理解——
    对docker一些认知
    selenium之css selector定位
    selenium之xpath定位
    Linux常用命令:修改文件权限chmod 754/744
    对redis的一些理解
    用户登录 用例设计
    mysql优化
    mysql复制问题
  • 原文地址:https://www.cnblogs.com/bamanzi/p/rsync-gotchas.html
Copyright © 2020-2023  润新知