delay=0不等于实时同步,因inotify仅通知“修改动作”而非“写入完成”,易触发未关闭文件的rsync;稳定低延迟需inotifyMode="CloseWrite"+delay=1–5秒+maxProcesses=1。

能,但“低延迟”不等于“零延迟”,关键在 delay、inotifyMode 和事件聚合策略的组合控制;盲目设 delay = 0 反而容易触发大量小文件并发 rsync,导致失败或传输半截文件。
为什么 delay = 0 不等于实时同步
lsyncd 的事件监听基于 inotify,但 inotify 通知的是“文件被修改”这个动作,不是“文件已写完”。比如 vim 编辑保存时会先写 .swp,再重命名覆盖原文件,中间可能触发多次事件。若 delay = 0,lsyncd 会立刻调用 rsync,此时目标端可能收到未关闭的文件句柄或不完整内容。
-
delay = 0实际含义是“不等待聚合,每个事件都立即触发 sync”,但 rsync 本身有启动开销,频繁调用反而增加失败率 - 真正稳定的低延迟区间是
delay = 1–5秒:足够让编辑器完成写入闭环(如 vim 的CloseWrite),又不会明显感知卡顿 - 必须配合
inotifyMode = "CloseWrite"(而非默认的"Modify"),否则连单次保存都会被拆成多次事件
如何配置出可靠 sub-5 秒响应的同步链路
核心不是压低 delay,而是减少无效事件 + 控制并发 + 确保 rsync 调用时机合理:
- 设置
inotifyMode = "CloseWrite":只在文件写入完成并关闭时才触发,过滤掉中间状态 - 设
delay = 3:给系统留出缓冲窗口,合并同一秒内多个变更(例如批量 touch 10 个文件,只跑一次 rsync) - 强制
maxProcesses = 1:避免多个 rsync 进程争抢 SSH 连接或目标目录锁(尤其 rsyncssh 模式下) - 加
rsyncOpts = {"--size-only"}(可选):跳过时间戳比对,仅靠大小+内容校验,加快判断速度 - 排除临时文件必须用
excludeFrom+ 提前建好/etc/lsyncd_exclude.lst,内容如:*~\n*.swp\n*.tmp\n.git/\n
,仅靠exclude字段无法拦截 inotify 中途事件
rsyncssh 模式下影响延迟的隐藏瓶颈
即使配置看起来没问题,SSH 层和远端 rsync 启动耗时常常是最大延迟来源:
- 远端用户 shell 不能是
/bin/false或/usr/sbin/nologin,否则 SSH 会拒绝执行 rsync 命令,表现为日志里反复出现ssh: connect to host xxx port 22: Connection refused或空连接后退出 - 确保远端已安装 rsync(
which rsync返回有效路径),且版本 ≥ 3.1(lsyncd 2.2.1+ 要求) - 如果 SSH 端口非 22,
host字段必须写成"user@host:port"格式,漏掉冒号或写成port=xxx都会导致解析失败、超时重试 - 禁用 SSH 密钥协商耗时:在
ssh子块中加_extra = {"-o ConnectTimeout=3", "-o ServerAliveInterval=15"}
验证是否真低延迟:别只看日志时间戳
日志里 Syncing X files 的时间不代表文件已在远端就绪。实际验证要抓两个点:
- 用
inotifywait -m -e close_write /path/to/source在源端观察事件触发时刻 - 在目标端运行
inotifywait -m -e attrib,close_write /path/to/target,对比两个时间差 - 注意:首次同步或大文件传输时,rsync 本体耗时远大于 lsyncd 调度耗时,这时延迟主要取决于网络和磁盘 IO,不是配置问题
真正容易被忽略的是 inotify 事件丢失——当每秒变更超过 8192 个文件(inotify 默认限制),inotifyMode 再准也收不到通知。此时得调高 /proc/sys/fs/inotify/max_user_watches,否则你会看到日志里安静得诡异,却始终不同步。


















