当前位置:首页 > 技术 > 正文内容

Linux环境下使用inotify与sersync实现rsync实时数据同步

访客 技术 2026年6月16日 1

一、 inotify 与 rsync 的基础整合

在数据备份与分发场景中,传统的定时任务(如 Cron)结合 rsync 无法满足毫秒级或秒级的实时性需求。自 Linux 内核 2.6.13 起,系统原生支持 inotify 文件系统监控机制。通过将 inotify 与 rsync 结合,可以构建高效的实时数据同步架构。

目前主流的 inotify 封装工具包括 inotify-tools、sersync 和 lsyncd。本文将首先剖析 inotify-tools 的底层机制与局限性,随后引入企业级解决方案 sersync。

1. 环境准备与 inotify-tools 部署

在使用 inotify 之前,需确认系统内核支持并检查相关内核参数。可以通过 sysctl 命令查看和调整 inotify 的资源限制:

# 查看当前 inotify 内核参数
sysctl fs.inotify.max_queued_events
sysctl fs.inotify.max_user_instances
sysctl fs.inotify.max_user_watches

# 临时调高监控数量上限(适用于海量文件目录)
sysctl -w fs.inotify.max_user_watches=30000000
sysctl -w fs.inotify.max_queued_events=327679

参数说明:

  • max_queued_events:inotify 实例的事件队列最大长度。若超出此值,将触发 Q_OVERFLOW 事件并丢弃后续事件。
  • max_user_instances:单个用户可创建的 inotify 实例总数上限。
  • max_user_watches:单个 inotify 实例可监控的文件/目录节点总数。监控大型项目时必须调大此值。

安装 inotify-tools(以源码编译为例):

wget https://github.com/inotify-tools/inotify-tools/archive/refs/tags/3.22.1.0.tar.gz
tar -xf 3.22.1.0.tar.gz
cd inotify-tools-3.22.1.0
./autogen.sh && ./configure --prefix=/opt/inotify
make && make install
ln -sv /opt/inotify/bin/inotifywait /usr/local/bin/

2. inotifywait 核心参数与事件模型

inotifywait 是 inotify-tools 的核心组件,用于阻塞或持续监听文件系统事件。常用参数如下:

  • -m:持续监控模式,不随单次事件退出。
  • -r:递归监控目录及其所有子目录。
  • -q:静默模式,仅输出必要信息。
  • -e:指定监听的事件类型(如 close_write, delete, moved_to)。
  • --exclude:使用正则表达式排除特定文件或目录。
  • --format:自定义输出格式,如 '%w%f %e'

在实际同步场景中,并非所有事件都需要关注。例如,access(读取)和 open(打开)事件对数据同步毫无意义。推荐使用以下事件组合:

  • close_write:文件写入完成并关闭(核心同步触发点)。
  • delete:文件或目录被删除。
  • moved_to / moved_from:文件移入或移出监控目录。
  • create,isdir:创建新目录(确保目录结构同步)。

3. 架构部署位置说明

在典型的"一主多从"发布架构中(例如 1 台发布机,3 台 Web 节点),inotify 必须部署在数据源端(发布机)。发布机监控本地目录变化,并作为 rsync 客户端主动将变更推送到配置为 rsync daemon 的 Web 节点。这种"推"模式能最大程度保证数据分发的实时性。

二、 inotify+rsync 脚本实现与性能调优

1. 基础同步脚本(存在性能缺陷)

以下是一个常见的入门级监控脚本。该脚本通过管道将 inotifywait 的输出直接传递给 rsync:

#!/bin/bash
SRC_DIR="/data/webroot"
DEST_HOST="192.168.1.100"
RSYNC_MODULE="web_sync"

inotifywait -mrq -e close_write,delete,moved_to,moved_from --format '%w%f' "$SRC_DIR" | while read -r CHANGED_FILE; do
    # 每次文件变化都触发全目录同步
    rsync -avz --delete "$SRC_DIR/" "rsync_user@${DEST_HOST}::${RSYNC_MODULE}/"
done

缺陷分析:当向监控目录批量拷贝 1000 个文件时,inotifywait 会产生 1000 次事件,导致 rsync 被连续调用 1000 次。虽然 rsync 具备增量比对机制,但频繁的进程创建、网络握手和目录遍历会消耗大量 CPU 和 I/O 资源,甚至导致同步延迟。

2. inotify 的已知缺陷与竞态条件

在使用 inotifywait -r 递归监控时,如果目标目录结构较深且包含大量文件,在目录创建的瞬间,底层 C 代码存在竞态条件(Race Condition),会导致部分 close_write 事件随机丢失。这意味着如果脚本仅针对"发生变化的单个文件"进行精准同步,极易造成数据漏传。

此外,使用 Vim 等编辑器修改文件时,会产生 .swp.swx~ 后缀的临时文件。如果不加过滤,这些临时文件会被同步到生产环境,可能引发不可预知的故障。

3. 优化版批量同步脚本

为了解决频繁调用 rsync 的问题,我们可以引入"日志缓冲与批量处理"机制。将事件写入日志文件,通过轮询日志文件的状态来触发 rsync,从而将多次事件合并为一次或两次同步操作:

#!/bin/bash
MONITOR_PATH="/data/webroot"
REMOTE_IP="192.168.1.100"
MODULE_NAME="web_sync"
EVENT_LOG="/var/log/inotify_batch.log"

# 1. 初始全量同步,确保基线一致
rsync -avz --delete --exclude="*.swp" --exclude="*.swx" "$MONITOR_PATH/" "rsync_user@${REMOTE_IP}::${MODULE_NAME}/"

# 2. 后台持续监控并记录事件(排除临时文件)
inotifywait -mrq -e close_write,delete,moved_to,moved_from,create \
    --exclude '\.swp$|\.swx$|.*~' \
    --format '%w%f' "$MONITOR_PATH" > "$EVENT_LOG" &

# 3. 轮询日志文件,触发批量同步
while true; do
    if [ -s "$EVENT_LOG" ]; then
        # 执行目录级同步
        rsync -avz --delete --exclude="*.swp" --exclude="*.swx" "$MONITOR_PATH/" "rsync_user@${REMOTE_IP}::${MODULE_NAME}/"
        
        # 清空日志,防止下一轮重复同步
        truncate -s 0 "$EVENT_LOG"
        
        # 补偿同步:防止在清空日志瞬间产生的新事件被遗漏
        rsync -avz --delete --exclude="*.swp" --exclude="*.swx" "$MONITOR_PATH/" "rsync_user@${REMOTE_IP}::${MODULE_NAME}/"
    else
        # 无事件时休眠,降低 CPU 占用
        sleep 2
    fi
done

此脚本通过 truncate 清空日志并辅以二次补偿同步,在保证数据完整性的前提下,将 rsync 的调用频率降低了数个数量级。

三、 sersync:企业级实时同步引擎

尽管优化后的 Shell 脚本能缓解性能问题,但在处理 TB 级数据、高并发写入以及失败重试等复杂场景时,仍显力不从心。sersync 是一款基于 C++ 编写的专业级 inotify 封装工具,专为 rsync 实时同步设计。

1. sersync 的核心优势

  • 事件过滤与去重:自动过滤临时文件,合并短时间内的重复事件,大幅减少 rsync 调用。
  • 多线程并发:支持多线程调用 rsync,显著提升海量小文件的同步吞吐量。
  • 失败重试机制:内置错误队列,对同步失败的文件进行定时重传。
  • 内置定时全量比对:无需依赖系统 crontab,即可配置周期性的整体目录校验。

2. 部署与配置

sersync 为绿色免安装软件,解压即可使用。建议将其放置于 /opt/sersync 目录:

wget https://github.com/wsgzao/sersync/raw/master/sersync2.5.4_64bit_binary_stable_final.tar.gz
tar -xf sersync2.5.4_64bit_binary_stable_final.tar.gz
mv GNU-Linux-x86 /opt/sersync
ln -sv /opt/sersync/sersync2 /usr/local/bin/

sersync 的核心行为由 confxml.xml 文件控制。以下是一份经过优化的生产环境配置示例:

<?xml version="1.0" encoding="ISO-8859-1"?>
<head version="2.5">
    <host hostip="localhost" port="8008"></host>
    <debug start="false"/>
    <fileSystem xfs="false"/>
    
    <!-- 过滤规则:排除不需要监控的文件或目录 -->
    <filter start="true">
        <exclude expression="(.*)\.svn"></exclude>
        <exclude expression="(.*)\.git"></exclude>
        <exclude expression="^logs/*"></exclude>
        <exclude expression="(.*)\.swp"></exclude>
    </filter>
    
    <!-- 监控事件类型配置 -->
    <inotify>
        <delete start="true"/>
        <createFolder start="true"/>
        <createFile start="false"/>
        <closeWrite start="true"/>
        <moveFrom start="true"/>
        <moveTo start="true"/>
        <attrib start="false"/>
        <modify start="false"/>
    </inotify>

    <sersync>
        <!-- 本地监控路径与远程目标配置 -->
        <localpath watch="/data/webroot">
            <remote ip="192.168.1.100" name="web_sync"/>
        </localpath>
        
        <rsync>
            <commonParams params="-avz --delete"/>
            <auth start="true" users="rsync_user" passwordfile="/etc/rsyncd.secret"/>
            <userDefinedPort start="false" port="873"/>
            <timeout start="true" time="300"/>
            <ssh start="false"/>
        </rsync>
        
        <!-- 失败重试机制:每 60 分钟执行一次失败重传 -->
        <failLog path="/opt/sersync/rsync_fail_log.sh" timeToExecute="60"/>
        
        <!-- 定时全量同步:每 12 小时进行一次整体目录比对 -->
        <crontab start="true" schedule="720">
            <crontabfilter start="true">
                <exclude expression="*.tmp"></exclude>
                <exclude expression="logs/*"></exclude>
            </crontabfilter>
        </crontab>
    </sersync>
</head>

3. 启动与多实例管理

配置完成后,使用 sersync2 命令启动服务。常用参数包括:

  • -d:以守护进程模式在后台运行。
  • -r:在启动监控前,先执行一次全量 rsync 推送,确保两端数据基线一致。
  • -o:指定自定义的 XML 配置文件路径(用于多实例场景)。
  • -n:指定并发线程数(默认 10,可根据 CPU 核心数调整)。

启动单实例服务:

sersync2 -r -d -o /opt/sersync/confxml.xml

若需同时监控多个不同的业务目录(如 Nginx 配置目录和 Web 代码目录),只需复制并修改 XML 配置文件,然后分别启动即可:

# 实例 1:同步 Web 代码
sersync2 -r -d -o /opt/sersync/conf_web.xml

# 实例 2:同步 Nginx 配置
sersync2 -r -d -o /opt/sersync/conf_nginx.xml

通过 sersync 的多实例与多线程特性,可以在复杂的微服务或集群架构中,轻松实现低延迟、高可靠的数据实时分发。

标签: rsync

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。