
你有三台Web服务器,前面挂了个负载均衡。用户访问,哪台空闲就去哪台。一切都很美好。
直到你更新了网站的某个图片。你改了第一台。用户刷新,有的看到新图片,有的还是旧的。
因为第二台、第三台上还是老文件。
怎么让它们自动保持一致?今天教你这个技能。
先看一个场景
一个做电商的朋友,两台服务器跑同样的网站。每次上新商品,他要登录两台机器,分别上传图片。有一次忘了传第二台,一半用户看到新商品,一半看不到。
客户投诉“你们网站是不是有bug”。他花了半天解释,最后把两台机器手动同步了一遍。
他说:“要是能改一台,另一台自动跟着改,就好了。”
能。而且不难。
整体思路
用两个工具配合:
- rsync:同步文件的工具。能比对差异,只传输变化的部分。
- inotify:Linux内核的一个功能,能监控文件变化。文件新建、修改、删除,它都知道。
工作流程:
- inotify监控主服务器上的某个目录
- 一旦发现文件变化,立即触发rsync
- rsync把变化同步到其他服务器
效果:你在主服务器上改一个文件,其他服务器几乎同时更新。
第一步:准备工作
假设有两台服务器:
- 主服务器:
192.168.1.10(文件更新源) - 备服务器:
192.168.1.20(接收同步)
1. 配置SSH免密登录
从主服务器能免密登录到备服务器。之前的文章讲过,ssh-keygen生成密钥,ssh-copy-id把公钥传过去。
测试:
bash
ssh root@192.168.1.20
不需要输密码,就对了。
2. 安装rsync
两台都装:
bash
apt install rsync -y # Ubuntu/Debian yum install rsync -y # CentOS
3. 安装inotify-tools(只装主服务器)
bash
apt install inotify-tools -y # Ubuntu/Debian yum install epel-release -y && yum install inotify-tools -y # CentOS
第二步:写一个rsync同步脚本
在主服务器创建脚本/root/sync.sh:
bash
#!/bin/bash # 源目录(要同步的文件夹) SRC_DIR="/var/www/html/" # 目标服务器和目录 DEST_USER="root" DEST_IP="192.168.1.20" DEST_DIR="/var/www/html/" # rsync同步 rsync -avz --delete $SRC_DIR $DEST_USER@$DEST_IP:$DEST_DIR echo "同步完成:$(date)"
参数解释:
-a:归档模式,保留权限、时间戳-v:显示详细信息-z:传输时压缩--delete:如果主服务器删了文件,备服务器也删
给执行权限:
bash
chmod +x /root/sync.sh
手动跑一次测试:
bash
/root/sync.sh
去备服务器的/var/www/html看看,文件是不是同步过来了。
第三步:写inotify监控脚本
inotify可以监控目录,一旦有变化就执行脚本。
创建监控脚本/root/watch.sh:
bash
#!/bin/bash
# 要监控的目录
WATCH_DIR="/var/www/html/"
# 监控事件:修改、创建、删除、移动
/usr/bin/inotifywait -m -r -e modify,create,delete,move --format '%w%f' $WATCH_DIR | while read FILE
do
echo "检测到变化:$FILE"
/root/sync.sh
done
解释:
-m:持续监控-r:递归监控子目录-e:监控的事件类型--format:输出格式,只输出文件名
给执行权限:
bash
chmod +x /root/watch.sh
第四步:运行并测试
前台运行看看效果:
bash
/root/watch.sh
保持终端开着。在主服务器的/var/www/html目录里:
bash
echo "test" > /var/www/html/test.txt
你会看到监控脚本输出“检测到变化”,然后执行rsync。
去备服务器检查:
bash
cat /var/www/html/test.txt
应该能看到同样的内容。
按Ctrl+C停止监控。
第五步:后台运行(生产环境)
确认功能正常后,让它在后台一直运行。
可以写一个systemd服务,或者用screen/tmux。
用screen(简单):
bash
screen -S sync /root/watch.sh
按Ctrl+A然后按D,后台运行。
下次想查看日志:
bash
screen -r sync
用systemd服务(推荐):
创建/etc/systemd/system/sync-watch.service:
ini
[Unit] Description=File Sync Watch After=network.target [Service] Type=simple ExecStart=/root/watch.sh Restart=always User=root [Install] WantedBy=multi-user.target
启动服务:
bash
systemctl daemon-reload systemctl enable sync-watch systemctl start sync-watch systemctl status sync-watch
常见问题和优化
问题1:大量文件变化时,rsync频繁执行
解决:inotifywait加--timeout或者写个防抖逻辑,比如变化后等1秒再执行。
问题2:同步自己的修改导致循环
解决:备服务器不要监控同步目录(或者只在主服务器开监控)。
问题3:断网时怎么办
解决:rsync本身支持断点续传,网络恢复后,下次变化会触发同步。也可以再加一个定时任务兜底(比如每小时同步一次)。
问题4:同步大文件(如视频)
解决:大文件变化慢,可以用--bwlimit限速,避免占满带宽。
一个真实案例
有个做图片网站的朋友,两台服务器,图片存在本地磁盘。每次摄影师上传新图,他要手动同步到另一台,经常漏。
我帮他配了rsync+inotify。摄影师上传后,几秒钟内,所有服务器都有新图片了。他说:“以后我再也不用半夜爬起来传文件了。”
最后一句
多台服务器不是各自为战。
配好实时同步,你在一台上改一个文件,所有服务器自动更新。负载均衡放心切,用户不会看到“半新半旧”的网站。
花半小时配置,以后省下的时间,够你做更多有意义的事。
今天就在测试环境试试。你的服务器们,该统一了。




