
1. 项目概述为什么需要实时同步在运维的日常里数据备份和同步是个老生常谈但又绝不能掉以轻心的话题。传统的定时任务备份比如用crontab每天凌晨跑一次rsync对于很多业务场景来说已经越来越不够用了。想象一下你负责一个内容发布系统编辑刚上传了一篇重要的新闻稿或者财务系统刚生成了一份关键的报表如果这些文件要等到半夜才被同步到备份服务器中间这十几个小时的数据空窗期风险是显而易见的。硬件故障、误操作、甚至勒索软件都可能在这段时间内造成无法挽回的数据丢失。这就是“实时”或“准实时”同步的价值所在。它追求的是在源端数据发生变更后尽可能快地将变更同步到目标端将RPO恢复点目标从小时级、天级压缩到分钟级甚至秒级。我见过太多因为备份不及时只能找回一天前的旧数据导致业务遭受严重损失的案例。所以当业务对数据的连续性和可用性要求越来越高时搭建一套轻量、可靠、近乎实时的文件同步机制就从“锦上添花”变成了“雪中送炭”。而rsync sersync这个组合就是实现这个目标的经典方案之一尤其在Linux环境下。它不是什么高深莫测的新技术而是将两个久经考验的老兵巧妙地组合在一起发挥出“112”的效果。rsync负责高效、差异化的数据传输sersync则扮演一个敏锐的“哨兵”实时监控文件系统的变化并触发同步。这个方案的优势在于架构清晰、资源消耗相对可控并且对网络中断等异常情况有一定的容忍度。接下来我就结合自己多次部署和踩坑的经验把这个组合从设计思路到实操细节再到避坑指南完整地拆解一遍。2. 核心组件解析rsync与sersync各司其职要玩转这个组合首先得吃透两个核心组件的工作原理和角色定位。很多人一开始容易混淆觉得sersync是不是一个更高级的rsync其实完全不是它们分工明确。2.1 rsync高效的数据同步引擎rsync绝对可以称得上是Linux世界里的“传输神器”。它的核心能力不是简单的文件拷贝而是增量同步。我打个比方如果你有一个10GB的大文件只修改了其中1MB的内容传统的scp或cp需要重新传输整个10GB文件而rsync通过其独特的算法可以只传输这1MB的差异部分这对于节省带宽和缩短同步时间来说是革命性的。它的工作模式主要分为两种作为远程Shell命令通过SSH通道执行就像我们常用的rsync -avz /local/path userremote-host:/remote/path。这种方式简单直接利用了现有的SSH安全认证但需要在目标机器上安装rsync并且每次同步都需要建立SSH连接。以守护进程Daemon模式运行这是在生产环境更推荐的方式。在目标服务器上启动一个rsync守护进程配置好模块、路径和认证。源服务器则作为客户端去连接这个守护进程进行同步。这种方式效率更高更适合脚本化、自动化调用也是我们与sersync配合时采用的标准模式。rsync守护进程的配置文件通常是/etc/rsyncd.conf里面定义了同步的模块、路径、授权用户和密码文件等。它的可靠性经过了无数生产环境的验证但短板也很明显它本身不具备主动监控文件变化的能力只是一个被动的、按需执行同步命令的工具。2.2 sersync专注的Inotify事件监听器sersync的角色就是补上rsync“被动”的这个短板。它的核心是基于Linux内核的Inotify机制。Inotify可以监控文件或目录的多种事件比如创建IN_CREATE、修改IN_MODIFY、删除IN_DELETE、移动IN_MOVE等。sersync就是一个用C编写的、专门利用Inotify API的守护程序。它启动后会对你指定的目录进行递归监控。一旦监控的目录下有文件事件发生sersync会立刻捕获到这个事件。但sersync自己并不处理文件同步它的标准做法是触发一个预定义好的shell命令最常见的就是调用rsync客户端命令将发生变化的文件同步到远程服务器。这里有一个非常重要的设计考量事件过滤与合并。如果没有这个机制后果会很严重。假设你在监控的目录里一次性拖入了1000张图片Inotify会瞬间产生1000个IN_CREATE事件。如果sersync对每个事件都立即触发一次rsync那么它会瞬间fork出1000个rsync进程这足以让你的服务器瞬间卡死。优秀的sersync实现比如金山开源的那个版本会有一个队列和延时合并机制比如在10秒内收集到的事件合并后只触发一次同步或者对同一文件的频繁修改只触发一次最终同步。这个机制是sersync能否稳定运行的关键。所以总结一下分工sersync是眼睛和耳朵负责发现变化rsync是腿和手负责执行同步。两者通过一个shell命令桥接起来构成了一个完整的实时同步流水线。3. 架构设计与环境准备在动手敲命令之前花点时间规划好架构能避免后期很多麻烦。一个典型的生产环境架构涉及两台服务器源服务器Source和目标服务器Target。源服务器生产数据产生的源头。需要安装sersync因为它需要Inotify来监控和rsync作为客户端来推送数据。目标服务器数据备份的目的地。只需要安装并运行rsync守护进程以接收来自源服务器的数据。从网络和权限角度看需要确保源服务器能通过网络通常是SSH或873端口访问目标服务器。目标服务器上为rsync守护进程准备的备份目录其属主和权限要配置正确确保源服务器通过rsync用户有写入权限。防火墙需要放行相应的端口如果使用rsync daemon模式默认是873/tcp。工具选型与安装rsync绝大多数Linux发行版都自带通过yum install rsync(RHEL/CentOS) 或apt install rsync(Debian/Ubuntu) 即可安装。重点在于配置。sersync这里有个小坑。网上很多教程提到的“sersync”通常特指金山公司开源的那个版本其项目地址在Google Code上现在可能不太好直接下载。你可以搜索“sersync2.5.4_64bit_binary_stable_final.tar.gz”这样的包名从可靠的镜像站获取。或者你也可以考虑它的“竞品”比如lsyncd。lsyncd 功能更强大配置方式不同使用Lua脚本且通常包含在发行版仓库中yum install lsyncd。本文仍以经典的金山sersync为例进行讲解因为它的配置相对更集中、直观。注意从第三方下载二进制程序时务必在测试环境先验证其安全性和稳定性。如果公司有严格的安全规定建议从源码编译或使用发行版官方仓库提供的替代品如lsyncd。4. 目标服务器配置rsync守护进程我们的同步流程是从源推到目标所以先在目标服务器上把“接收端”配置好。4.1 创建备份目录与权限设置假设我们打算把备份放在/data/backup_from_source目录下。sudo mkdir -p /data/backup_from_source sudo chown -R nobody:nogroup /data/backup_from_source # 使用nobody用户运行rsync daemon是常见做法 sudo chmod -R 755 /data/backup_from_source这里将目录所有者设为nobody是因为后面rsync守护进程默认可能以这个低权限用户运行确保它有写入权。你也可以创建一个专门的用户如rsync_backup。4.2 编辑rsync守护进程配置文件配置文件通常是/etc/rsyncd.conf如果不存在就创建它。sudo vim /etc/rsyncd.conf写入以下内容# /etc/rsyncd.conf uid nobody gid nogroup use chroot no max connections 10 pid file /var/run/rsyncd.pid lock file /var/run/rsyncd.lock log file /var/log/rsyncd.log # 传输日志便于排查 transfer logging yes # 超时设置 timeout 300 # 定义一个模块名字叫 [backup_module]客户端同步时就指定这个名字 [backup_module] # 备份数据存放的路径 path /data/backup_from_source # 注释说明 comment Backup directory from source server # 是否只读这里必须为 false 以允许写入 read only false # 是否列出模块内容出于安全考虑生产环境建议设为 false list false # 允许连接的IP地址设置为源服务器的IP或者整个网段 192.168.1.0/24 hosts allow 192.168.1.100 # 拒绝所有其他主机 hosts deny 0.0.0.0/0 # 认证用户虚拟用户非系统用户 auth users rsync_user # 存储密码的文件路径里面存放 rsync_user 的密码 secrets file /etc/rsyncd.secrets关键参数解读[backup_module]模块名后续在sersync配置和手动测试时都会用到。hosts allow这是重要的安全设置务必限制为源服务器IP避免服务暴露给全网。auth users和secrets file用于身份验证。rsync_user是一个虚拟用户名不需要在系统上真实存在。4.3 创建密码文件并设置权限创建密码文件/etc/rsyncd.secretssudo vim /etc/rsyncd.secrets内容格式为用户名:密码一行一个rsync_user:YourStrongPassword123!极其重要的一步这个文件包含了明文密码所以必须将其权限设置为仅root可读否则rsync会拒绝启动。sudo chmod 600 /etc/rsyncd.secrets sudo chown root:root /etc/rsyncd.secrets4.4 启动rsync守护进程并设置开机自启启动服务# 对于使用systemd的系统CentOS 7, Ubuntu 16.04 sudo systemctl start rsyncd sudo systemctl enable rsyncd # 检查状态和日志 sudo systemctl status rsyncd sudo tail -f /var/log/rsyncd.log如果系统没有rsync的systemd服务文件可以手动以守护进程方式启动rsync --daemon --config/etc/rsyncd.conf可以将其写入/etc/rc.local实现开机自启。在目标服务器上使用netstat -tlnp | grep 873命令应该能看到rsync在监听873端口说明守护进程启动成功。5. 源服务器部署与配置sersync目标服务器准备好后我们回到源服务器进行操作。5.1 安装sersync假设你已经下载了sersync2.5.4_64bit_binary_stable_final.tar.gz。# 解压到合适目录例如 /opt sudo tar -zxvf sersync2.5.4_64bit_binary_stable_final.tar.gz -C /opt cd /opt # 解压后通常是一个名为 GNU-Linux-x86 的目录可以重命名一下 sudo mv GNU-Linux-x86/ sersync cd sersync目录里主要文件有sersync2主程序二进制文件。confxml.xml核心配置文件。sersync2默认已经有可执行权限。5.2 详解并编辑sersync配置文件confxml.xml是这个方案的核心我们需要仔细配置。?xml version1.0 encodingISO-8859-1? head version2.5 host hostiplocalhost port8008/host !-- 这部分一般不用动 -- debug startfalse/ !-- 调试模式默认关闭排查问题时可以临时开启 -- fileSystem xfsfalse/ !-- 如果是XFS文件系统设为true -- filter startfalse !-- 过滤器可以过滤掉临时文件等例如 -- exclude expression(.*)\.svn/exclude exclude expression(.*)\.gz/exclude exclude expression^info/*/exclude exclude expression^static/*/exclude /filter inotify !-- Inotify相关配置核心 -- delete starttrue/ !-- 是否监控删除事件 -- createFolder starttrue/ !-- 是否监控创建文件夹事件 -- createFile startfalse/ !-- 创建文件事件通常由modify事件覆盖可关 -- closeWrite starttrue/ !-- 文件关闭写入事件即修改完成最关键的事件 -- moveFrom starttrue/ !-- 移出事件 -- moveTo starttrue/ !-- 移入事件 -- attrib startfalse/ !-- 属性变更事件如chmod通常不需要 -- modify startfalse/ !-- 修改事件与closeWrite类似但时机不同 -- /inotify sersync !-- sersync主配置 -- localpath watch/data/to_be_synced !-- 要监控的本地目录 -- remote ip192.168.1.200 namebackup_module/ !-- 目标服务器IP和rsync模块名 -- !--remote ip192.168.88.10 nametongbu/-- !-- 可以配置多个远程服务器 -- !--remote ip192.168.88.11 nametongbu/-- /localpath rsync !-- rsync命令配置 -- commonParams params-artuz/ !-- rsync通用参数a归档模式r递归t保持时间u跳过更新的z压缩 -- auth starttrue usersrsync_user passwordfile/etc/rsync.pas/ !-- 认证信息 -- userDefinedPort startfalse port874/!-- 如果目标rsync端口不是873在此指定 -- timeout startfalse time100/!-- 超时设置 -- ssh startfalse/ !-- 是否使用SSH模式我们用的是daemon模式所以是false -- /rsync failLog path/tmp/rsync_fail_log.sh timeToExecute60/!-- 失败重试脚本很实用的功能 -- crontab startfalse schedule600!-- 定时全量同步作为实时同步的补充 -- crontabfilter startfalse exclude expression*.php/exclude exclude expressioninfo/*/exclude /crontabfilter /crontab plugin startfalse namecommand/ !-- 插件功能如同步后执行命令 -- /sersync plugin namecommand !-- 命令插件配置示例 -- param prefix/bin/sh suffix ignoreErrortrue/ !--prefix /bin/sh -c suffix-- filter startfalse include expression(.*)\.php/ include expression(.*)\.sh/ /filter /plugin plugin namesocket !-- 其他插件一般不用 -- localpath watch/opt/tongbu deshost ip192.168.138.20 port8009/ /localpath /plugin plugin namerefreshCDN !-- 其他插件一般不用 -- localpath watch/data0/htdocs/cms.xoyo.com/site/ cdninfo domainnameccms.chinacache.com port80 usernamexxxx passwdxxxx/ sendurl basehttp://pic.xoyo.com/cms/ regexurl regexfalse matchcms.xoyo.com/site([/a-zA-Z0-9]*).xoyo.com/images/ /localpath /plugin /head你需要修改的关键部分localpath watch/data/to_be_synced将其中的路径改为你源服务器上需要被实时监控同步的目录。remote ip192.168.1.200 namebackup_module/将ip改为你的目标服务器IPname改为目标服务器上配置的rsync模块名我们之前配置的是backup_module。auth starttrue usersrsync_user passwordfile/etc/rsync.pas/这里配置认证。users对应目标服务器上rsyncd.secrets里定义的用户名。passwordfile是源服务器本地存放密码的文件。5.3 在源服务器创建密码文件在源服务器上创建密码文件/etc/rsync.pas注意这个文件只包含密码不包含用户名并且权限必须是600。sudo vim /etc/rsync.pas输入密码YourStrongPassword123!设置权限sudo chmod 600 /etc/rsync.pas sudo chown root:root /etc/rsync.pas5.4 手动测试rsync连通性在启动sersync之前强烈建议先用rsync命令手动测试一次确保从源到目标的整个rsync通道是通的。# 在源服务器执行 rsync -avz /data/to_be_synced/ rsync_user192.168.1.200::backup_module --password-file/etc/rsync.pas-avz归档模式、显示详情、压缩传输。/data/to_be_synced/注意后面的/表示同步目录内的内容而不是目录本身。如果想同步目录本身则去掉/。rsync_user192.168.1.200::backup_modulersync_user是认证用户192.168.1.200是目标服务器IPbackup_module是模块名。--password-file/etc/rsync.pas指定密码文件。如果这条命令能成功将文件推送到目标服务器的/data/backup_from_source目录下说明rsync配置完全正确。这一步能排除掉90%的权限、网络、认证问题。5.5 启动sersync服务测试通过后就可以启动sersync了。cd /opt/sersync # 前台启动便于观察日志 ./sersync2 -d -o confxml.xml-d以守护进程模式运行。-o指定配置文件。还可以加-n参数指定线程数默认为10监控目录文件特别多时可以适当增加。启动后可以查看进程和日志ps aux | grep sersync tail -f /opt/sersync/rsync_rsync.log # 同步日志现在你可以在/data/to_be_synced目录下创建、修改或删除文件观察日志和备份目录应该能看到近乎实时的同步动作。5.6 配置sersync开机自启为了确保服务稳定性需要配置开机自启。创建一个systemd服务文件是最规范的方式。sudo vim /etc/systemd/system/sersync.service写入以下内容[Unit] DescriptionSersync Real-time File Synchronization Afternetwork.target [Service] Typeforking ExecStart/opt/sersync/sersync2 -d -o /opt/sersync/confxml.xml ExecStop/bin/kill -TERM $MAINPID Restarton-failure RestartSec10 Userroot Grouproot [Install] WantedBymulti-user.target然后启用并启动服务sudo systemctl daemon-reload sudo systemctl enable sersync sudo systemctl start sersync sudo systemctl status sersync6. 高级配置与性能调优基础搭建完成后为了应对更复杂的生产环境还需要考虑一些高级配置和性能调优点。6.1 过滤规则精细化配置配置文件中的filter标签非常有用。比如你监控的是Web服务器的上传目录可能会产生很多临时文件如.upload_tmp或者缓存文件这些文件不需要同步。又比如开发目录下的.git、node_modules等目录体积巨大且无需备份。通过合理配置过滤可以大幅减少不必要的同步事件和网络流量。filter starttrue exclude expression^\.git//exclude !-- 过滤.git目录 -- exclude expression.*\.tmp$/exclude !-- 过滤所有.tmp结尾的临时文件 -- exclude expression.*\.swp$/exclude !-- 过滤vim交换文件 -- exclude expression^node_modules//exclude !-- 过滤node_modules -- exclude expression^\.DS_Store$/exclude !-- 过滤Mac系统文件 -- /filter表达式使用正则语法^表示开头$表示结尾。开启过滤 (starttrue) 后被匹配到的文件或目录将不会被监控也就不会触发同步。6.2 失败重试与定时全量补偿网络抖动、目标服务器短暂不可用等情况难免发生。sersync提供了两个补救机制失败重试队列 (failLog): 当某次同步失败时失败的指令会被记录到指定的脚本文件如/tmp/rsync_fail_log.sh中。你可以设置一个定时任务cron job定期比如每分钟执行这个脚本重试失败的同步。这是一个很好的最终一致性保障。定时全量同步 (crontab): 在配置中可以开启crontab starttrue schedule600这里的schedule单位是秒600秒10分钟。这意味着即使没有文件事件sersync也会每隔10分钟强制进行一次全目录的rsync同步。这可以纠正可能因事件丢失Inotify队列溢出导致的源和目标之间细微的不一致。注意对于大目录频繁全量同步可能带来性能压力需要权衡。6.3 性能调优参数Inotify限制Linux内核对于Inotify有默认限制主要是max_user_watches单个用户可监控的文件/目录数和max_user_instances单个用户可创建的inotify实例数。如果你监控的目录下文件数量极多例如超过几十万可能会遇到No space left on device的错误。# 查看当前限制 cat /proc/sys/fs/inotify/max_user_watches # 临时调整重启失效 sudo sysctl -w fs.inotify.max_user_watches1048576 # 永久调整在 /etc/sysctl.conf 中添加 fs.inotify.max_user_watches1048576 fs.inotify.max_user_instances1024sersync线程数通过-n参数指定例如./sersync2 -d -n 20 -o confxml.xml。默认10个线程。如果监控目录非常繁忙事件产生极快可以适当增加线程数以避免事件堆积。但线程数并非越多越好需要观察CPU和IO负载。rsync参数优化在confxml.xml的commonParams中调整。对于大量小文件可以加上-W全量拷贝不计算差异有时反而更快但耗带宽。对于网络质量好、文件大的场景-z压缩很有用。--bwlimit可以限制同步带宽避免影响生产业务。7. 监控、排查与日常维护一套系统跑起来监控和日志分析是保证其长期稳定运行的关键。7.1 关键监控指标进程存活最简单的用ps aux | grep sersync或systemctl status sersync检查进程是否在运行。同步延迟可以在源目录创建一个带时间戳的标记文件然后观察目标目录该文件出现的时间计算差值。更专业的可以用Zabbix、Prometheus等监控工具通过解析sersync的日志或自定义脚本获取延迟指标。Inotify事件队列如果事件产生速度超过处理速度事件会堆积。可以观察系统日志/var/log/messages或使用dmesg | grep inotify查看是否有相关警告。sersync自身的日志也会有所体现。系统资源监控源服务器的CPU、内存、IO特别是inotify相关的内核开销以及网络带宽使用情况。7.2 日志分析与问题排查sersync和rsync都会产生日志是排查问题的第一现场。sersync日志默认在运行目录下如/opt/sersync/rsync_rsync.log。这里记录了每次被触发执行的rsync命令及其结果。如果同步失败这里会有错误信息。rsync守护进程日志在目标服务器的/var/log/rsyncd.log配置文件中指定。这里记录了每一次连接、认证和文件传输的详情。权限拒绝、模块不存在等问题在这里看最清楚。常见问题速查表问题现象可能原因排查步骤sersync启动失败配置文件XML格式错误监控目录不存在密码文件权限不对。1. 用xmllint检查confxml.xml格式。2. 检查localpath目录是否存在。3. 检查/etc/rsync.pas权限是否为600。手动rsync测试成功但sersync不同步sersync监控的事件类型未覆盖你的操作过滤规则误杀了文件。1. 检查inotify配置确保closeWrite和createFolder等为true。2. 检查filter规则是否过于宽泛。可以临时关闭过滤 (startfalse) 测试。同步报错auth failed源/目标服务器密码文件内容或格式错误密码文件权限不对。1. 确认源服务器/etc/rsync.pas只有密码目标服务器/etc/rsyncd.secrets是用户:密码。2. 确认两个密码文件权限均为600。同步报错permission denied目标服务器备份目录的属主/权限不对rsync守护进程配置的uid/gid无写入权限。1. 检查目标服务器/data/backup_from_source目录确保运行rsync的用户如nobody有写权限。2. 检查rsyncd.conf中的uid/gid设置。大量小文件同步慢或CPU高rsync在计算大量小文件的差异网络延迟高。1. 考虑调整rsync参数尝试-W慎用首次全量后可关。2. 评估是否可以使用归档工具如tar打包后再同步但这破坏了实时性。3. 检查网络质量。监控大量文件时报No space left on device达到max_user_watches内核限制。按6.3节方法调大/proc/sys/fs/inotify/max_user_watches值。7.3 日常维护建议定期检查日志每天花几分钟看一眼关键日志有没有持续的报错或警告。验证数据一致性定期比如每周使用rsync -n干跑模式或diff、md5sum等命令抽样比对源和目标的关键文件确保同步没有静默失败。备份配置将修改好的confxml.xml、rsyncd.conf等配置文件纳入版本管理如Git。压力测试在业务低峰期模拟大规模文件变更如解压一个大型tar包到监控目录观察系统负载和同步延迟评估方案的极限能力。制定应急预案明确如果sersync进程挂掉、目标服务器磁盘满等情况下的处理流程和恢复步骤。8. 方案对比与替代选择rsyncsersync方案成熟稳定但并非唯一选择。了解其他方案有助于你在不同场景下做出最佳选择。lsyncd前面提到过它是sersync的一个强大替代品。它同样基于Inotify但使用Lua语言配置更加灵活。可以配置为rsync、rsyncssh、direct本地cp等多种同步模式甚至支持多级同步和自定义动作。对于复杂需求lsyncd可能是更好的选择。inotify-tools rsync 脚本最原始的方案。使用inotifywait命令监控目录在事件触发时执行自定义的shell脚本调用rsync。这种方式灵活性最高但需要自己处理事件队列、去重、错误重试等逻辑稳健性需要仔细打磨。DRBD (Distributed Replicated Block Device)工作在块设备层实现磁盘块的实时镜像。数据一致性最强相当于RAID1 over network。但配置相对复杂且对网络要求极高通常用于高可用集群的主备数据同步而非简单的文件备份。GlusterFS, Ceph 等分布式文件系统这些系统本身提供了多副本机制文件写入时自动同步到多个节点。这属于架构层面的解决方案适用于新建系统而非在现有单机系统上叠加同步层。云存储同步工具如AWS的DataSync、阿里云的ossutil配合事件触发等。如果目标端是云对象存储使用厂商提供的工具往往在带宽优化、断点续传、集成度上更有优势。选择哪个方案取决于你的具体需求是要求强一致性还是最终一致性同步延迟要求多高数据量有多大是海量小文件还是大文件运维团队更熟悉哪种技术栈rsyncsersync在简单性、资源消耗和可靠性上取得了很好的平衡对于大多数“将一台服务器上的目录实时同步到另一台服务器”的场景它依然是一个非常值得推荐的选择。它的价值在于用最小的学习和部署成本构建了一道可靠的数据安全防线。