【集群实战】inotify
1. inotify简介
Inotify是一种强大的,细粒度的,异步的文件系统事件监控机制(软件)。
linux内核从2.6.13起,加入了Inotify支持,通过Inotify可以监控文件系统中添加,删除,修改,移动等各种事件,利用这个内核接口,第三方软件就可以监控文件系统下文件的各种变化情况,而inotify-tools正是实施这样监控的软件。还有国人周洋在金山公司开发的sersync。
Inotify实际是一种事件驱动机制,它为应用程序监控文件系统事件提供了实时响应事件的机制,而无须通过诸如cron等的轮询机制来获取事件。
cron等机制不仅无法做到实时性,而且消耗大量系统资源。
相比之下,inotify基于事件驱动,可以做到对事件处理的实时响应,也没有轮询造成的系统资源消耗,是非常自然的事件通知接口,也与自然世界的事件机制相符合。
inotify 的实现有几款软件
- inotify-tools,
- sersync(金山周洋)
- lsyncd
2. 实时同步系统架构拓扑
下面的inotify配置是建立在rsync服务基础上的配置过程。

3. inotify 实施准备
大前提rsync daemon 服务配置成功,可以再rsync客户端推送拉取数据,然后才能配置inotify服务。
4. inotify安装
默认yum源:
- base + extras + updates
扩展的yum源:
epel
- 网易163源
- 阿里云epel源
在安装inotify-tools前请先确认你的linux内核是否达到了2.6.13,并且在编译时开启CONFIG_INOTIFY选项,也可以通过以下命令检测。
4.1 查看当前系统是否支持inotify
[root@nfs-31 data]# uname -r
2.6.32-573.el6.x86_64
[root@nfs-31 data]# ls -l /proc/sys/fs/inotify/
total 0
-rw-r--r-- 1 root root 0 Dec 12 18:59 max_queued_events
-rw-r--r-- 1 root root 0 Dec 12 18:59 max_user_instances
-rw-r--r-- 1 root root 0 Dec 12 18:59 max_user_watches # 显示这三个文件则证明支持inotify
关键参数说明:
- 在/proc/sys/fs/inotify目录下有三个文件,对inotify机制有一定的限制
- max_user_watches:设置inotifywait或inotifywatch命令可以监视的文件数量(单进程)
- max_user_instances:设置每个用户可以运行的inotifywait或inotifywatch命令的进程数。
- max_queued_events:设置inotify实例事件(event)队列可容纳的事件数量。
[root@nfs-31 inotify]# ls|xargs head
==> max_queued_events <==
16384 ==> max_user_instances <==
128 ==> max_user_watches <==
8192
4.2 安装inotify软件
[root@nfs-31 inotify]# rpm -qa inotify-tools
[root@nfs-31 inotify]# yum install inotify-tools -y # Error: Nothing to do
安装失败,用wget获取源,再用yum安装:
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-6.repo
yum -y install inotify-tools
[root@nfs-31 inotify]# rpm -qa inotify-tools
inotify-tools-3.14-2.el6.x86_64
一共安装了2个工具,即inotifywait和inotifywatch。
- inotifywait:在被监控的文件或目录上等待特定文件系统事件(open,close,delete等)发生,执行后处于阻塞状态,适合shell脚本中使用。
- inotifywatch:收集被监视的文件系统使用度统计数据,指文件系统事件发生的次数统计。
5. inotifywait命令
[root@nfs-31 inotify]# which inotifywait
/usr/bin/inotifywait [root@nfs-31 inotify]# /usr/bin/inotifywait --help
inotifywait 3.14
Wait for a particular event on a file or set of files.
Usage: inotifywait [ options ] file1 [ file2 ] [ file3 ] [ ... ]
Options:
-h|--help Show this help text.
@<file> Exclude the specified file from being watched.
--exclude <pattern>
Exclude all events on files matching the
extended regular expression <pattern>.
--excludei <pattern>
Like --exclude but case insensitive.
-m|--monitor Keep listening for events forever. Without # 监听
this option, inotifywait will exit after one
event is received.
-d|--daemon Same as --monitor, except run in the background # 守护进程
logging events to a file specified by --outfile.
Implies --syslog.
-r|--recursive Watch directories recursively. # 递归,对子目录进行监控
--fromfile <file>
Read files to watch from <file> or `-' for stdin.
-o|--outfile <file>
Print events to <file> rather than stdout.
-s|--syslog Send errors to syslog rather than stderr.
-q|--quiet Print less (only print events).
-qq Print nothing (not even events).
--format <fmt> Print using a specified printf-like format
string; read the man page for more details.
--timefmt <fmt> strftime-compatible format string for use with
%T in --format string.
-c|--csv Print events in CSV format.
-t|--timeout <seconds>
When listening for a single event, time out after
waiting for an event for <seconds> seconds.
If <seconds> is 0, inotifywait will never time out.
-e|--event <event1> [ -e|--event <event2> ... ] # 事件
Listen for specific event(s). If omitted, all events are
listened for. Exit status:
0 - An event you asked to watch for was received.
1 - An event you did not ask to watch for was received
(usually delete_self or unmount), or some error occurred.
2 - The --timeout option was given and no events occurred
in the specified interval of time. Events: # 监控的事件类型:访问,修改,属性发生变化;写之后关闭,只读之后关闭,所有关闭动作;移动到,从某处移动,移动;创建,删除,删除了,卸载
access file or directory contents were read
modify file or directory contents were written
attrib file or directory attributes changed
close_write file or directory closed, after being opened in
writeable mode
close_nowrite file or directory closed, after being opened in
read-only mode
close file or directory closed, regardless of read/write mode
open file or directory opened
moved_to file or directory moved to watched directory
moved_from file or directory moved from watched directory
move file or directory moved to or from watched directory
create file or directory created within watched directory
delete file or directory deleted within watched directory
delete_self file or directory was deleted
unmount file system containing file or directory unmounted
比较重要的参数的含义:
| inotifywait参数 | 含义说明 |
|---|---|
| -r --recursive | 递归查询目录 |
| -q --quiet | 打印很少的信息,仅仅打印监控事件的信息 |
| -m,--monitor | 始终保持事件监听状态 |
| --exclude | 排除文件或目录时,不区分大小写。 |
| --timefmt | 指定时间输出的格式 |
| --format | 打印使用指定的输出类似格式字符串 |
| -e,--event | 通过此参数可以指定需要监控的事件,如下一个列表所示 |
-e,--event 事件的各种事件含义:
| Events | 含义 |
|---|---|
| access | 文件或目录被读取 |
| modify | 文件或目录内容被修改 |
| attrib | 文件或目录属性被改变 |
| close | 文件或目录封闭,无论读/写模式 |
| open | 文件或目录被打开 |
| moved_to | 文件或目录被移动至另外一个目录 |
| move | 文件或目录被移动到另一个目录或从另一个目录移动至当前目录 |
| create | 文件或目录被创建在当前目录 |
| delete | 文件或目录被删除 |
| umount | 文件系统被卸载 |
--format 的格式意义:
- %w 发生事件的监视文件的名称
- This will be replaced with the name of the Watched file on which an event occurred.
- %f 当一个事件发生在一个目录中时,它将被替换为导致该事件发生的文件名。否则,将替换为空字符串。
- When an event occurs within a directory, this will be replaced with the name of the File which caused the event to occur. Otherwise, this will be replaced with an empty string.
- %e 发生的事件,以逗号分隔。
- Replaced with the Event(s) which occurred, comma-separated.
- %Xe 发生的事件,用“X”中的任何字符分隔。
- Replaced with the Event(s) which occurred, separated by whichever character is in the place of ‘X’.
- %T 替换为--timefmt选项指定格式的当前时间,该格式字符串应适合传递给strftime(3)。
- Replaced with the current Time in the format specified by the --timefmt option, which should be a format string suitable for passing to strftime(3).
5.1 人工测试监控事件
开启两个窗口
5.1.1 测试create事件
在第一个窗口开启inotifywait,监听/backup目录:
[root@nfs-31 inotify]# inotifywait -mrq --timefmt '%y/%m/%d %H:%M' --format '%T %w%f' -e create /backup
# 命令说明:
# -mrq:-m 实时监听,-r递归监控整个目录,包括子目录,-q 只输出简短信息
# --timefmt:指定输出的时间格式
# --format:输出输出的格式
# -e create:指定监控的事件类型,监控创建create事件
第二个窗口,进入/backup目录,创建两个文件,触发create事件
[root@nfs-31 backup]# cd /backup
[root@nfs-31 backup]# touch inotifywait_create_event_1
[root@nfs-31 backup]# touch inotifywait_create_event_2
触发事件后,查看第一个窗口会发现,屏幕输出了创建事件的内容(时间和创建的文件路径加名称)
[root@nfs-31 inotify]# inotifywait -mrq --timefmt '%y/%m/%d %H:%M' --format '%T %w%f' -e create /backup
19/12/12 19:26 /backup/inotifywait_create_event_1
19/12/12 19:41 /backup/inotifywait_create_event_2
5.2.2 测试其它事件
在第一个窗口,执行inotifywait -mrq --timefmt '%y/%m/%d %H:%M' --format '%T %e %w%f' /backup 监听/backup目录。
在第二个窗口执行下面命令,不指定-e参数,默认会记录所有事件。
[root@nfs-31 backup]# cd /backup
[root@nfs-31 backup]# ls
192.168.0.31 flag_2019-12-05 logs_2019-12-05.tar.gz www_2019-12-07.tar.gz
config_2019-12-05.tar.gz flag_2019-12-07 logs_2019-12-07.tar.gz www_2019-12-08.tar.gz
config_2019-12-07.tar.gz flag_2019-12-08 logs_2019-12-08.tar.gz www_2019-12-09.tar.gz
config_2019-12-08.tar.gz flag_2019-12-09 logs_2019-12-09.tar.gz www_2019-12-10.tar.gz
config_2019-12-09.tar.gz flag_2019-12-10 logs_2019-12-10.tar.gz www_2019-12-11.tar.gz
config_2019-12-10.tar.gz flag_2019-12-11 logs_2019-12-11.tar.gz www_2019-12-12.tar.gz
config_2019-12-11.tar.gz flag_2019-12-12 logs_2019-12-12.tar.gz
config_2019-12-12.tar.gz inotifywait_create_event_1 test
flag_2019-12-03 inotifywait_create_event_2 www_2019-12-05.tar.gz
[root@nfs-31 backup]# touch inotifywait_create_event_3
[root@nfs-31 backup]# rm inotifywait_create_event_3
rm:是否删除普通空文件 "inotifywait_create_event_3"?y
[root@nfs-31 backup]# vi inotifywait_create_event_1
[root@nfs-31 backup]# mv inotifywait_create_event_1 test/
查看inotifywait监听窗口
[root@nfs-31 inotify]# inotifywait -mrq --timefmt '%y/%m/%d %H:%M' --format '%T %e %w%f' /backup
19/12/12 20:31 OPEN,ISDIR /backup/
19/12/12 20:31 CLOSE_NOWRITE,CLOSE,ISDIR /backup/ # ls 触发的所有事件 # touch inotifywait_create_event_3 触发的所有事件
19/12/12 20:43 CREATE /backup/inotifywait_create_event_3
19/12/12 20:43 OPEN /backup/inotifywait_create_event_3
19/12/12 20:43 ATTRIB /backup/inotifywait_create_event_3
19/12/12 20:43 CLOSE_WRITE,CLOSE /backup/inotifywait_create_event_3 # rm inotifywait_create_event_3 触发的事件
19/12/12 20:43 DELETE /backup/inotifywait_create_event_3 # vi inotifywait_create_event_1 并编辑了“123”再保存退出的所有触发事件
19/12/12 20:44 OPEN,ISDIR /backup/
19/12/12 20:44 CLOSE_NOWRITE,CLOSE,ISDIR /backup/
19/12/12 20:44 OPEN,ISDIR /backup/
19/12/12 20:44 CLOSE_NOWRITE,CLOSE,ISDIR /backup/
19/12/12 20:44 OPEN,ISDIR /backup/
19/12/12 20:44 CLOSE_NOWRITE,CLOSE,ISDIR /backup/
19/12/12 20:44 OPEN,ISDIR /backup/
19/12/12 20:44 CLOSE_NOWRITE,CLOSE,ISDIR /backup/
19/12/12 20:44 CREATE /backup/.inotifywait_create_event_1.swp
19/12/12 20:44 OPEN /backup/.inotifywait_create_event_1.swp
19/12/12 20:44 CREATE /backup/.inotifywait_create_event_1.swpx
19/12/12 20:44 OPEN /backup/.inotifywait_create_event_1.swpx
19/12/12 20:44 CLOSE_WRITE,CLOSE /backup/.inotifywait_create_event_1.swpx
19/12/12 20:44 DELETE /backup/.inotifywait_create_event_1.swpx
19/12/12 20:44 CLOSE_WRITE,CLOSE /backup/.inotifywait_create_event_1.swp
19/12/12 20:44 DELETE /backup/.inotifywait_create_event_1.swp
19/12/12 20:44 CREATE /backup/.inotifywait_create_event_1.swp
19/12/12 20:44 OPEN /backup/.inotifywait_create_event_1.swp
19/12/12 20:44 MODIFY /backup/.inotifywait_create_event_1.swp
19/12/12 20:44 MODIFY /backup/.inotifywait_create_event_1.swp
19/12/12 20:44 CREATE /backup/inotifywait_create_event_1
19/12/12 20:44 OPEN /backup/inotifywait_create_event_1
19/12/12 20:44 MODIFY /backup/inotifywait_create_event_1
19/12/12 20:44 CLOSE_WRITE,CLOSE /backup/inotifywait_create_event_1
19/12/12 20:44 MODIFY /backup/.inotifywait_create_event_1.swp
19/12/12 20:44 CLOSE_WRITE,CLOSE /backup/.inotifywait_create_event_1.swp
19/12/12 20:44 DELETE /backup/.inotifywait_create_event_1.swp # mv inotifywait_create_event_1 test/ 触发的事件
19/12/12 20:45 MOVED_FROM /backup/inotifywait_create_event_1
19/12/12 20:45 MOVED_TO /backup/test/inotifywait_create_event_1
6. 编写inotify实时监控脚本
[root@nfs-31 /]# cd /server/scripts
[root@nfs-31 scripts]# ls
backup.sh
[root@nfs-31 scripts]# vi inotifywait_nfs_to_backup.sh
[root@nfs-31 scripts]# cat inotifywait_nfs_to_backup.sh
#!/bin/bash Path=/data
backup_Server=192.168.0.41 /usr/bin/inotifywait -mrq --format '%w%f' -e close_write,delete $Path|while read line
do
if [ -f $line ];then
rsync -az $line --delete rsync_backup@$backup_Server::nfsbackup --password-file=/etc/rsync.password
else
cd $Path &&\
rsync -az ./ --delete rsync_backup@$backup_Server::nfsbackup --password-file=/etc/rsync.password
fi
done
脚本可以加入开机启动:
echo "/bin/sh /server/scripts/inotifywait_nfs_to_backup.sh &" >> /etc/rc.local
提示:
一个& 代表从后台开始运行该条命令
7. inotify加入chkconfig服务管理
通过start/stop控制/server/scripts/inotifywait_nfs_to_backup.sh脚本的启动和停止。
[root@nfs-31 init.d]# cat syncd
#!/bin/bash
#
# chkconfig: 2345 30 60
# this scripts is created by zoe . /etc/init.d/functions Sh_filename=inotifywait_nfs_to_backup.sh if [ $# -ne 1 ];then
usage: $0 {start|stop}
exit 1
fi case "$1" in
start)
/bin/bash /server/scripts/$Sh_filename &
echo $$ >/var/run/inotify.pid
if [ `ps -ef|grep inotify|wc -l` -gt 2 ];then
action "inotify service is started" /bin/true
else
action "inotify service is started" /bin/false
fi
;;
stop)
kill -9 cat /var/run/inotify.pid >/dev/null 2>&1
pkill inotifywait
sleep 2
if [ `ps -ef|grep inotify|grep -v grep|wc -l` -eq 0 ];then
action "inotify service is stopped" /bin/true
else
action "inotify service is stopped" /bin/false
fi
;;
*)
usage: $0 {start|stop}
exit 1
esac
加入开机自启动:
chkconfig --add syncd
chkconfig --list syncd
测试
/etc/init.d/syncd start
/etc/init.d/syncd stop
8. /proc/sys/fs/inotify三个关键参数调整
在/proc/sys/fs/inotify目录下有三个文件,对inotify机制有一定的限制
- max_user_watches:设置inotifywait或inotifywatch命令可以监视的文件数量(单进程)
- max_user_instances:设置每个用户可以运行的inotifywait或inotifywatch命令的进程数。
- max_queued_events:设置inotify实例事件(event)队列可容纳的事件数量。(一般不用调整,128已经很大了)
[root@nfs-31 inotify]# ls|xargs head
==> max_queued_events <==
16384 ==> max_user_instances <==
128 ==> max_user_watches <==
8192
调整:
[root@nfs-31 data]# echo 50000000 > /proc/sys/fs/inotify/max_user_watches
[root@nfs-31 data]# echo 326790 > /proc/sys/fs/inotify/max_queued_events
调整后,重启可能会失效。所以,为了实现每次开机生效,将命令放到/etc/rc.local中。
[root@nfs-31 data]# tail -3 /etc/rc.local
# set inotify watch and event max value
echo 50000000 > /proc/sys/fs/inotify/max_user_watches
echo 326790 > /proc/sys/fs/inotify/max_queued_events
9. Rsync+inotify实时数据同步并发简单测试
实时同步并发测试:
10k-100k文件
测试脚本:
每秒100个并发:
[root@nfs01 data]# paste inotify_100_server.log
inotify_100_backup_server.log > inotify_100.txt
[root@nfs01 data]# cat inotify_100.txt
23:05 34227 23:05 34227
23:05 34387 23:05 34387
23:05 35027 23:05 35027
23:05 35587 23:05 35587
23:05 36473 23:05 36473
23:05 36707 23:05 36707
23:05 37587 23:05 37587
以下省略...
Inotify实时并发:
结论:经过测试,每秒200文件并发,数据同步几乎无延迟(小于1秒)
inotify的优缺点
inotify 优点:
- 监控文件系统事件变化,通过同步工具实现实时数据同步。
inotify 缺点:
- 并发如果大于200个文件(10-100k),同步就会有延迟
- 我们前面写的脚本,每次都是全部推送一次,但确实是增量的。也可以只同步变化的文件,不变化的不理。
- 监控到事件后,调用rsync同步是单进程的,而sersync为多进程同步。
既然有了inotify-tools,为什么还要开发sersync?
解答:
serysync功能多:(inotify+rsync命令)
- 支持通过配置文件管理
- 真正的守护进程socket
- 可以对失败文件定时重传(定时任务功能)
- 第三方的HTTP接口(例如:更新cdn缓存)
- 默认多进程rsync同步
高并发数据实时同步方案小结:

- inotify(sersync)+ rsync,是文件级别的。(效率不高)
- drbd文件系统级别,文件系统级别,基于block块同步(效率高)缺点:备节点数据不可用,只有主节点坏了才能用。
- 第三方软件的同步功能:
- mysql同步(主从复制),oracle,mongodb
- 程序双写,直接写两台服务器。
- 利用产品业务逻辑解决(读写分离,备份读不到,读主)

说明:
用户上传的图片或者附件单独存在NFS主服务器上;
用户读取数据从两台NFS备份服务器上读取;
NFS主和两台NFS备份通过inotify+rsync方式进行实时同步。
- NFS集群(1,4,5方案整合)(双写主存储,备存储用inotify(sersync)+rsync,备存储没有找主存储,解决延迟问题)
- 弃用NFS方案(读写分离)
- 弃用方案就是写入到nfs服务器,nfs的备份直接备份到web服务器,用户读取直接从web服务器读取。

【集群实战】inotify的更多相关文章
- redis3.0 集群实战1 -- 安装和配置
本文主要是在centos7上安装和配置redis集群实战 参考: http://hot66hot.iteye.com/blog/2050676 集群教程: http://redisdoc.com/to ...
- 《跟老男孩学Linux运维:Web集群实战》读书笔记
Linux 介绍 Linux 安装 Linux 调优 Web 基础 Nginx 应用 LNMP 应用 PHP 缓存加速 Nginx 调优 MySQL 应用 NFS 网络文件共享 Nginx 反向代理与 ...
- MySQL/MariaDB数据库的Galera高可用性集群实战
MySQL/MariaDB数据库的Galera高可用性集群实战 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Galera Cluster概述 1>.什么是Gale ...
- Haproxy+keepalived高可用集群实战
1.1 Haproxy+keepalived高可用集群实战 随着互联网火热的发展,开源负载均衡器的大量的应用,企业主流软件负载均衡如LVS.Haproxy.Nginx等,各方面性能不亚于硬件负载均衡 ...
- 基于Ambari Server部署HDP集群实战案例
基于Ambari Server部署HDP集群实战案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.部署Ambari Server端 博主推荐阅读: https://www.c ...
- 【集群实战】Rsync数据同步工具
1. Rsync介绍 1.1 什么是Rsync? Rsync是一款开源的,快速的,多功能的,可实现全量及增量的本地或远程数据同步备份的优秀工具.Rsync软件适用于unix/linux/windows ...
- 高负载集群实战之lvs负载均衡-技术流ken
lvs简介 LVS的英文全称是Linux Virtual Server,即Linux虚拟服务器. 特点 跨平台:window,linux 作用 实现负载均衡 核心组件 ip_vs:linux的内核功能 ...
- Mongodb 集群实战
该实战过程完全跟着官网一步一步实现 ,官网教程:https://docs.mongodb.com/manual/tutorial/atlas-free-tier-setup/ 使用Mongo Shel ...
- activemq的高级特性:集群实战
高级特性实战需求 当消费端是多个集群,集群A又包含多个服务. 当每个集群都要接受相同的一批消息,而集群内的每个服务都去分摊消息. 解决办法一:级联 增加一个中转者.但是不是特别的优化,而且性能也不是特 ...
随机推荐
- linux下shell脚本中sed命令的用法
先来给一个案例: #将old.sql文件中的符号“|”替换为“,”,并保存到test.sql文件中 sed "s/|/,/g" "old.sql"> te ...
- scratch 如何改变变量的作用域
在新建变量的时候,有个选项是“适用于所有角色”还是“仅适用于当前角色”.通常称前者为全局变量,所有角色都可以访问到这个变量:后者,称为局部变量,只能在当前角色里访问到这个变量.例如,在使用克隆功能时, ...
- Python模块---制作属于自己的有声小说
操作环境 Python版本: anaconda3 python3.7.4 操作系统: Ubuntu19.10 编译器: pycharm社区版 用到的模块: pyttsx3,requests pysst ...
- 数据结构和算法(Golang实现)(30)查找算法-2-3-4树和普通红黑树
文章首发于 阅读更友好的GitBook. 2-3-4树和普通红黑树 某些教程不区分普通红黑树和左倾红黑树的区别,直接将左倾红黑树拿来教学,并且称其为红黑树,因为左倾红黑树与普通的红黑树相比,实现起来较 ...
- 机器学习4- 多元线性回归+Python实现
目录 1 多元线性回归 2 多元线性回归的Python实现 2.1 手动实现 2.1.1 导入必要模块 2.1.2 加载数据 2.1.3 计算系数 2.1.4 预测 2.2 使用 sklearn 1 ...
- matplotlib IdentityTransform(原地变换)
2020-04-12 23:33:56 -- Edit by yangrayIdentityTransform继承于Affine2DBase类,它是一个高效实现原地变换的类.(不知道有什么用,变换前后 ...
- Django模拟ASP.NET MVC 自动匹配路由(转载)
项目结构 操作步骤 1.创建项目结构如上图 2.在myapp目录下创建urls文件,代码: from django.conf.urls import patterns, url from untitl ...
- 03 GUI界面的错误日志查看及清除
右上角图标,会显示当前使用工具的运行报错信息,点击可在下方查看到实际的错误日志
- HBase协处理器加载的三种方式
本文主要给大家罗列了HBase协处理器加载的三种方式:Shell加载(动态).Api加载(动态).配置文件加载(静态).其中静态加载方式需要重启HBase. 我们假设我们已经有一个现成的需要加载的协处 ...
- SpringMVC框架详细教程(四)_使用maven导入各个版本的Spring依赖包
使用maven导入Spring依赖包 上一节讲了如何向动态Web项目添加下载的Spring依赖包,作为补充下面列出了如何使用 maven 导入Spring的依赖包,可以选择需要的导入(推荐)或者全部导 ...