背景
我们日常都是用scp或rsync来同步目录和文件。但它们之间的区别是:rsync 是分块校验+传输,scp 是整个文件传输。rsync 比 scp 有优势的地方在于单个大文件的一小部分存在改动时,只需传输改动部分,无需重新传输整个文件。如果传输一个新的文件,理论上 rsync 没有优势。另外,rsync 不是加密传输,而 scp 是加密传输。使用时可以按需选择。用inotify+rsync做实时同步,来解决分布式集群文件一致性的问题。并且能够实时监控事件,当有监控事件发生时,执行相应操作。但如文件越来越多(例如:百万级数量html,jpg等小文件),同步就会越来越慢,根本做不到实时。网上的调优方法都尝试过,问题依旧。经过一翻细致研究和测试,终于找到问题点并解决。本篇文章做下记录。
环境
centos7
安装
1 | # 下载源码包 |
痛点分析
inotifywait单独分析
1 | /usr/local/inotify/bin/inotifywait -mrq --format '%Xe %w%f' -e modify,create,delete,attrib /data/ |
我们在/data/目录touch新建几个文件进行测试
1 | touch /data/{1..5} |
观看inotify输出
1 | # 前面表示事件,后面代表文件。格式是按照--format '%Xe %w%f'来输出的 |
根据输出结果,我们可以用rsync获取inotifywait监控到的文件列表来做指定的文件同步,而不是每次都由rsync做全目录扫描来判断文件是否存在差异。
网上的inotify+rsync分析
我们来看网上的教程,我加了注释。(网上所有的教程大同小异,尽管写法可能不一样,但致命点都是一样的)
1 |
|
分析:这里的rsync 每次都是整个目录全量同步,而file列表只是控制了循环次数而已,这就是问题所在。简单的说 :如有10个文件发生了更改,监听到了,file列表得到这个10个文件有改动,但仍然还要去触发10次rsync全量同步(简直就是噩梦),那还不如直接写个死循环的rsync全量同步呢。
辩论:有些同学会说,日志输出那里明明只有差异文件的同步记录。其实这是rsync的功能,它本来就只会输出有差异需要同步的文件信息,不信你直接拿这句rsync来测试看看。
影响:如需要同步的源目录文件量很大,并且目录一直有写入的情况下,那简直是噩梦。不仅消耗CPU资源还耗时,根本就做不到实时同步的目的。
优化测试
根据上面的分析,我们明白了问题所在,那么怎么去解决呢?
实时同步方法
必须要减少rsync对整个目录的全量递归扫描,尽可能的只同步inotify监控已发生更改的文件。
先上脚本
1 |
|
查漏补缺
我们通过上面脚本就可以进行实时同步,但是我们因为实时同步需求和同步速度等问题,只同步了监控开启后才发生了更改的文件。但没有启动inotify监控前和期间发生更改的文件,就做不到同步。所以这里我们每2个小时做1次全量同步,来防止各种意外遗漏,保证目录的一致性。
1 | # 写个定时任务 |
优化后在保证速度和一致性的前提,就可以实现百万级文件实时同步。
inotify的参数说明
inotify是一种强大的、细颗粒的、异步的文件系统监控机制。Linux内核从2.6.13起加入Inotify可以监控文件系统中添加、删除、修改移动等各种事件,利用这个内核接口,就可以监控文件系统下文件的各种变化情况。功能非常强大,但是也有局限性。挂载的文件存储目录就监控不到,据说sersync可以监控挂载目录,有兴趣同学可以自行调研学习。
参数说明
参数名称 | 参数说明 |
---|---|
-m,–monitor | 始终保持事件监听状态 |
-r,–recursive | 递归查询目录 |
-q,–quiet | 只打印监控事件的信息 |
–excludei | 排除文件或目录时,不区分大小写 |
-t,–timeout | 超时时间 |
–timefmt | 指定时间输出格式 |
–format | 指定时间输出格式 |
-e,–event | 后面指定删、增、改等事件 |
事件说明
事件名称 | 事件说明 |
---|---|
access | 读取文件或目录内容 |
modify | 修改文件或目录内容 |
attrib | 文件或目录的属性改变 |
close_write | 修改真实文件内容 |
close_nowrite | |
close | |
open | 文件或目录被打开 |
moved_to | 文件或目录移动到 |
moved_from | 文件或目录从移动 |
move | 移动文件或目录移动到监视目录 |
create | 在监视目录下创建文件或目录 |
delete | 删除监视目录下的文件或目录 |
delete_self | |
unmount | 卸载文件系统 |
优化配置
在/proc/sys/fs/inotify目录下有三个文件,对inotify机制有一定的限制
1 | [root@web ~]# ll /proc/sys/fs/inotify/ |
Rsync命令
六命令六模式
1 | # 六种命令格式 |
对应六种命令格式,rsync有六种工作模式:
- 拷贝本地文件。当SRC和DES路径信息都不包含有单个冒号”:”分隔符时就启动这种工作模式。如:rsync -a /data /backup
- 使用一个远程shell程序(如rsh、ssh)来实现将本地机器的内容拷贝到远程机器。当DST路径地址包含单个冒号”:”分隔符时启动该模式。如:rsync -avz *.c foo:src
- 使用一个远程shell程序(如rsh、ssh)来实现将远程机器的内容拷贝到本地机器。当SRC地址路径包含单个冒号”:”分隔符时启动该模式。如:rsync -avz foo:src/bar /data
- 从远程rsync服务器中拷贝文件到本地机。当SRC路径信息包含”::”分隔符时启动该模式。如:rsync -av root@172.16.78.192::www /databack
- 从本地机器拷贝文件到远程rsync服务器中。当DST路径信息包含”::”分隔符时启动该模式。如:rsync -av /databack root@172.16.78.192::www
- 列远程机的文件列表。这类似于rsync传输,不过只要在命令中省略掉本地机信息即可。如:rsync -v rsync://172.16.78.192/www
rsync参数:
1 | -v, --verbose 详细模式输出 |
总结
inotifywait响应是不会有延迟,rsync也很快,联动工作百万级数据同步,小case啦,前提是认真看完本教程,理解并举一反三运用。