海量文件的rsync同步方案
海量文件的rsync同步方案
zphj1987背景
如果一个环境需要对文件系统进行系统备份,文件系统内的文件数目是10亿级别的,那么直接通过一个rsync进行同步肯定是不太好的,如果出现中断,那么再次启动后的遍历的时间成本太高了
分析
rsync的同步原理是,启动同步的时候,会对源端进行一个全量的扫描,构建一个incremental file list,然后开始同步,如果是系统本地的目录进行同步我们可以看到三个进程
一个是生成器,一个是发送方,一个是接收方,因为是在一台机器上面运行,所以可以看到这三个进程的,这个之前还误以为是并发三,实际还是单进程模式的
我们很多情况下,存储环境都是集群模式的,集群模式就是文件系统有多个入口,可以多个并发同时去操作,比如我们原始集群有2个网关,我们新集群有6个网关,那么我们实际上是可以1个原始网关对3个新网关的方式去处理数据的
由于我们无法去判断原始的目录结构,并且即使能够获取到,也不太好去做均分,比如有6亿文件,根目录下面一个目录5亿,其它5个目录1亿,这种情况就不好去分平分目录了,还有个情况是如果按容量区分,也是不太好取到怎么去区分目录的,所以这个地方想到的一个方案是获取到所有的文件的列表,然后对列表做拆分,然后分配任务的方式
如何实现
如果能够拿到完整的文件列表,然后再对列表拆分就很好拆分了,比如9亿文件,我可以拆分成1000w一个任务,分成90份,然后平分给6个机器上面去,都是很好去做拆分的,拆大拆小都比较自由
获取文件的完整列表
1 | time rsync -av --dry-run /source/ /target/ > file_list.txt |
通过上面的命令可以完整的拿到文件的列表,/target目录是空目录
拿到的文件的格式如下
1 | sending incremental file list |
也就是这个文件我们需要删掉文件的第一行和文件的倒数两行还有目录
因为这个扫描会把目录扫描出来,我们是要文件同步,如果是包含目录,那么会出现重复的文件,所有的文件同步了,目录自然也是同步的,并且同步的时候目录rsync会自己处理好
如果这个文件是巨大的,那么我们处理文本文件的时候还是要注意下,本篇会考虑这种情况
拆分文件
拆分文件就是根据我们需要的任务数,然后拆分文件,首先需要统计文件的行数
1 | [root@myserver home]# time wc -l file_list.txt |
统计这个9个亿的文件列表的行数,需要90秒
看下文件的大小
1 | [root@myserver home]# ll file_list.txt |
9亿文件列表的大小为45G,这里建议拆分成2G左右一个文件,或者更小,我们拆分2G就是24份,用9亿除以24得到大概得文件数目,然后往高取整得到38267146这个值,也就是单个文件存储大概3800w条数据
我们使用slit命令拆分文件
1 | [root@myserver zpdisk]# time split -l 38267146 file_list.txt |
拆分的时间大概在10min左右,得到的文件大概2G
我们拆分完文件以后还要处理文件
处理文件列表
拆分出来的文件第一个文件的开头要去掉,最后一个文件的结尾去掉两行,中间每个文件都需要去掉目录
这里我们需要处理三个地方
1 | [root@myserver zpdisk]# time sed -i '1d' xaa |
处理开头的一行,这个需要大概1min
删除最后一行
1 | [root@myserver zpdisk]# time sed -i '$d' xax |
删除最后一行需要1min,要操作两次
删除列表里面的目录
1 | [root@myserver zpdisk]# time sed -i '/\/$/d' xaa |
这里一个文件需要处理大概1min,一共24个也就是总共时间24min
处理完成后我们就得到一个完整的文件列表了
使用列表
1 | rsync -av /source/ /target/ --files-from=xaa --log-file=/var/log/xaa.log |
一个列表对应一个命令,然后这个具体要并发开几个,这个就是很简单的事情了,一条命令对一个列表即可,剩下的事情就很简单了
补充
上面是同步的所有文件的情况,还有个情况是原始目录里面有可能有很多空目录,这个需要取一下列表
1 | [root@jenkins filelist]# cat checkkong.py |
执行方法
1 | time python3 checkkong.py filelistfile.txt > kong.txt |
删除第一行的./
1 | sed -i '1d' kong.txt |
然后同步这个空目录列表即可
1 | rsync -av --files-from=kongdir.list /zp/source/ /zp/target/ |
总结
总结下操作流程
- 拿列表
- 拆分列表
- 处理列表
- 使用列表
整体上的步骤就这四步了
时间和空间数据
上面是基于一个9亿文件的测试环境做的测试,有一些结果可以供参考
测试事项 | 时间/容量 | 单项计算时间 |
---|---|---|
9亿文件的获取列表时间 | 563min | 1亿文件需要62min |
9亿文件的本地文本占用 | 45G | 1亿文件需要占用5G |
9亿文件的本地文件统计行数 | 90s | |
9亿文件拆分成24个文件(3800w单文件) | 558s | |
3800w文件本地占用 | 2G | |
删除2G文本文件的开头一行 | 51s | |
删除2G文本文件的结尾一行 | 51s | |
删除2G文本文件的内的目录项 | 59s |