简介
??最近有一个比较特殊的需求,某个服务提供文件上传功能。但是由于要解决单点问题,所以会程序会部署在多台服务器上实现高可用。但是也会随之带来一个和共享cookie类似的问题,那就是文件存储也应该是共享的.其实大部分同学想到的,第一个肯定是使用NFS来解决。大家通过NFS mount到同一个目录即可实现. 但是为什么我们没有选择这个解决方案呢? 那是因为之前不知道是我们使用不当还是NFS自身存在问题, 出现了几次事故,NFS Server端卡死,导致整个NFS的client端由于使用【硬挂载】的方式一直卡住,整个服务器的负载因此也一直飙升,直到NFS Server端恢复正常或者管理员主动卸载mount才能将机器负载降下来恢复正常。在没弄明白原因之前,NFS就不太敢用了,只能另想他法.
rsync+inotify实现原理
原理图:
??我们最后采用了rsync+inotify的方式来解决我们这个需求。最初一开始,我对这个解决方案是排斥的。因为后期如果文件过多,势必带来性能和延迟问题。但是最终均衡和考虑业务量的情况下,还是采用了这种方式能暂时满足我们的需求.
??rsync是一个服务器之间进行文件同步的工具. 具体详情大家可以自行查资料。这里我们可以理解为可以实现文件内容对比的scp工具。如果文件内容没变化则不会发生同步文件的操作, 否则会同步最新内容使得目标服务器的文件内容一致。但是rsync只能做到的只是文件同步,它自身没有能力发现哪些文件内容发生了变化.你执行rsync命令让它同步哪个文件就同步哪个文件,仅此而已。那么我们要做到2台主机之间某个目录或者文件能够达到实时同步效果,需要借助其他工具进行辅助,最好能帮我们监控某个目录下的文件,一旦目录文件发生内容变动(如内容增加、内容减少、删除、修改等等),我们获取通知之后,再执行rsync命令,达到我们实时同步的目的。
??inotify是Linux下的一个工具,inotifywait是其中的一个组件,就能帮我们监控某个目录,一旦文件内容发送变动,我们会获取到一个事件通知,拿到文件的路径。之后我们通过自定义shell脚本,执行rsync命令,实现实时同步的目的。
安装与实现
B服务器(同步数据的目标服务器)
yum install rsync inotify-tools -y
uid = root
gid = root
use chroot = no
max connections = 20
pid file = /var/run/rsyncd.pid
log file = /var/log/rsyncd.log
lock file = /var/run/rsyncd.lock
[upload]
path = /
read only = no
auth users = rsync
secrets file = /etc/rsyncd.secrets
list = no
systemctl start rsyncd
A服务器(源数据服务器)
echo '密码' >> /etc/rsyncd.passwd
该脚本建议使用如supervisor等工具运行,进程保活,挂掉自动拉起:
set -ex
monitor_path='/tmp/'
sync_host='127.0.0.1'
sync_user='rsync'
sync_module='upload'
inotifywait -mrq --format '%w%f' -e create -e delete -e moved_to -e close_write $monitor_path | while read line
do
dir_name=`dirname $line`
if [ -f $line ];then
rsync -azrR $line --delete --password-file=/etc/rsyncd.passwd $sync_user@$sync_host::$sync_module
else
rsync -azrR $dir_name --delete --password-file=/etc/rsyncd.passwd $sync_user@$sync_host::$sync_module
fi
done
supervisor配置文件:
[program:inotify-rsync]
command=/bin/bash -c "/sh/shell/inotify-rsync.sh"
process_name=inotify-rsync
autorestart=true
startsecs=5
stopsignal=INT
stopasgroup=true
killasgroup=true
redirect_stderr=true
stdout_logfile_maxbytes=0
stdout_logfile=/sh/shell/inotify-rsync-running.log
|