数据同步--lsyncd

一、介绍

Lsyncd (Live Syncing Daemon) 轻量级本地与远程实时同步解决方案,遵循 GPL-2.0 license。
Lsyncd 使用文件系统事件接口(inotify 或 fsevents)来监视本地文件和目录的更改,并在短时内汇总合并事件,然后启动一个或多个进程将更改同步到远程文件系统,默认同步方式是 rsync 模式。
优点:

  • 实时同步(单向):lsyncd 通过监控文件系统事件(inotify 或 fsevents),可以在文件变化时触发同步;
  • 基于 rsync:使用 rsync 进行实际的文件传输,继承 rsync 高效性和灵活性;
  • 自动化:配置好,lsyncd 可以自动监控和同步文件变化;
  • 灵活性:通过 Lua 脚本配置,定制同步行为;

缺点:

  • 复杂性:配置文件高级用法可能对刚接触用户来说有些复杂;
  • 资源消耗:实时监控和同步可能会消耗一定的系统资源,特别是在有大量文件变化的情况下;
  • 延迟问题:尽管是实时同步,但对于非常频繁的变化,可能会有轻微的延迟;

使用场景:

  • 日志文件同步:在需要实时同步日志文件到远程服务器进行分析时,lsyncd 非常有用;
  • 实时备份:适用于需要实时备份重要数据的场景;
  • Web 服务器文件同步:在多台 Web 服务器之间同步静态文件,确保所有服务器上的文件保持一致。

作为 rsync 的替代方案,lsyncd 可以通过 rsync+ssh 模式提高同步效率,例如,重命名文件/目录或者移动位置(普通 rsync 通过删除旧文件然后重新传输整个文件来执行移动)。
原理:
lsyncd (Live Syncing Daemon) 是一个轻量级的同步守护进程,它内部结合了 inotify(监控文件变化)和 rsync(远程同步),并支持将短时间内的多个文件变化合并后一起同步,效率很高。
lsyncd 通过 inotify 机制持续监控 source 目录。只有当 source 里的文件发生了新增、修改或删除,它才会触发 rsync 把变化同步到 target。

二、安装与使用

相关机器:

  • 可以互通网络
  • 已安装 rsync
  • 已配置免密 SSH 登录(强烈建议)

2.1、安装

sudo apt install lsyncd rsync ssh -y
sudo systemctl start lsyncd
sudo systemctl enable lsyncd
日志:tail -f /var/log/lsyncd/lsyncd.log
lsyncd -version
rsync --version
ssh -V

2.2、配置 lsyncd

lsyncd 使用 Lua 配置文件,通常位于 /etc/lsyncd/lsyncd.conf.lua,也可以通过以下方式查看路径:
查看:systemctl status lsyncd

查看:/etc/init.d/lsyncd

默认配置路径:/etc/lsyncd/lsyncd.conf.lua,如果不存在则新建,或者从 /usr/share/doc/lsyncd*/examples 提供的示例中拷贝一份进行修改。

例如,下面配置:

Lua 复制代码
-- settings 表用于定义全局设置
settings {
   logfile    = "/var/log/lsyncd/lsyncd.log", -- 指定日志文件路径, 用于记录 lsyncd 的运行日志
   statusFile = "/var/log/lsyncd-status.log", -- 指定状态文件路径, 用于记录 lsyncd 的状态信息
   inotifyMode = "CloseWrite or Modify",      -- 指定 inotify 事件模式。默认是CloseWrite,还可以是Modify或CloseWrite or Modify
   statusInterval = 20,                       -- 每 20 秒写入一次状态文件
   maxProcesses = 1,                          -- 限制并发的进程数
   delay = 15,            -- 设置同步的延迟时间(秒)。若在sync中设置,这里可不设置
   nodaemon   = false      -- 是否以前台运行, false:后台守护进程,true:前台调试运行        
}

-- sync 表用于定义同步任务
sync {
    default.rsync,  -- 指定要使用的同步模式,常用的有default.rsync(使用 rsync 进行同步) ;default.direct :本地目录间同步,使用cp、rm等命令完成差异文件备份;default.rsyncssh :同步到远程主机目录,rsync的ssh模式,需要使用key来认证
    source = "/path/to/source/",                       -- 定义源目录的路径,使用绝对路径
    target = "user@remote_host:/path/to/destination/", -- 定义目标目录的路径,可以是本地路径或远程路径
    delay = 5,  -- 等待rsync同步延时时间,默认15秒(最大累计到1000个不可合并的事件)
    exclude = { "*.tmp", "*.log", "cache/", "temp/" },  -- 指定要排除的文件或目录的模式列表。相对于source的相对路径
    excludeFrom = "/path/to/exclude-list.txt", -- 指定一个包含要排除文件和目录列表的文件路径
    delete = true,   -- 为了保持target与souce完全同步,Lsyncd默认会delete = true来允许同步删除。它除了false,还有startup、running值
   
    rsync = {
        binary = "/usr/bin/rsync",  -- rsync 可执行文件路径
        archive = true,  -- 等同于 -a 参数,保留文件属性
        compress = true, -- 传输时压缩
        verbose = true   -- 显示详细输出
    }
}

这里的 delay 参数很关键,它能有效防止因文件高频变动而频繁触发同步带来的性能损耗**。**

三、案例说明

Lua 复制代码
settings {
    logfile    = "/var/log/lsyncd/lsyncd.log",
    statusFile = "/var/log/lsyncd-status.log",
    inotifyMode = "CloseWrite or Modify", 
    maxProcesses = 8
}


-- I. 本地目录同步,direct:cp/rm/mv。 适用:500+万文件,变动不大
sync {
    default.direct,
    source    = "/tmp/src",
    target    = "/tmp/dest",
    delay = 1
    maxProcesses = 1
}

-- II. 本地目录同步,rsync模式:rsync
sync {
    default.rsync,
    source    = "/tmp/src",
    target    = "/tmp/dest1",
    excludeFrom = "/etc/rsyncd.d/rsync_exclude.lst",
    rsync     = {
        binary = "/usr/bin/rsync",
        archive = true,
        compress = true,
        bwlimit   = 2000
    }
}


-- III. 远程目录同步,rsync模式 + rsyncd daemon
sync {
    default.rsync,
    source    = "/tmp/src",
    target    = "syncuser@172.29.88.223::module1",
    delete = "running",
    exclude = { ".*", ".tmp" },
    delay = 30,
    init = false,
   
    rsync     = {
        binary = "/usr/bin/rsync",
        archive = true,
        compress = true,
        verbose   = true,
        password_file = "/etc/rsyncd.d/rsync.pwd",
        _extra    = {"--bwlimit=200"}
    }
}

-- IV. 远程目录同步,rsync模式 + ssh shell
sync {
    default.rsync,
    source    = "/tmp/src",
    target    = "root@172.29.88.223:/remote/dest",  -- 上面target,注意如果是普通用户,必须拥有写权限
    maxDelays = 5,
    delay = 30,
    -- init = true,
    rsync     = {
        binary = "/usr/bin/rsync",
        archive = true,
        compress = true,
        bwlimit   = 2000
        -- rsh = "/usr/bin/ssh -p 22 -o StrictHostKeyChecking=no"
        -- 如果要指定其它端口,请用上面的rsh
    }
}

-- V. 远程目录同步,rsync模式 + rsyncssh,效果与上面相同
sync {
    default.rsyncssh,
    source    = "/tmp/src2",
    host      = "172.29.88.223",
    targetdir = "/remote/dir",
    excludeFrom = "/etc/rsyncd.d/rsync_exclude.lst",
    delay = 2,
    rsync    = {
        binary = "/usr/bin/rsync",
        archive = true,
        compress = true,
        verbose   = true,
        _extra = {"--bwlimit=2000"},
    },
    ssh = {
        port = 22
    }
}

四、配置 SSH 免密登录

lsyncd 会频繁调用 rsync,而 rsync 常通过 ssh 连接远端。为了避免每次都输入密码,需要配置 SSH key

python 复制代码
# 安装ssh-keygen和ssh-copy-id
apt install openssh-client

# 生成本地 SSH 密钥(如果已有可跳过)
ssh-keygen -t rsa -b 4096 -N "" -f ~/.ssh/id_rsa

# 将公钥复制到远程主机,(将本机的/root/.ssh/id_rsa.pub公钥复制到远程主机的/root/.ssh/authorized_keys文件)
ssh-copy-id gc@10.68.250.14

# 测试免密登录
ssh gc@10.68.250.14 "echo success"

五、实测

5.1、本地同步

配置:/etc/lsyncd/lsyncd.conf.lua

Lua 复制代码
-- settings 表用于定义全局设置
settings {
   logfile    = "/var/log/lsyncd/lsyncd.log",
   statusFile = "/var/log/lsyncd-status.log",
   inotifyMode = "CloseWrite or Modify",
   statusInterval = 20,                  
   maxProcesses = 1,  
   nodaemon   = false        
}

-- sync 表用于定义同步任务
sync {
    default.rsync,
    source = "/home/gc/lsyncd/source/",
    target = "gc@10.68.250.13:/home/gc/lsyncd/dest/",
    delay = 5,
    delete = true,
   
    rsync = {
        binary = "/usr/bin/rsync",
        archive = true,
        compress = true,
        verbose = true
    }
}

先建议前台运行检查配置是否正确: lsyncd -nodaemon /etc/lsyncd/lsyncd.conf.lua

在/home/gc/lsyncd/source/新建个test.py文件:

在/home/gc/lsyncd/source/下删除文件tiny-graphrag.zip:

修改在/home/gc/lsyncd/source/test.py:

修改在/home/gc/lsyncd/dest/test.py:
无输出

配置正确后后台运行 : lsyncd /etc/lsyncd/lsyncd.conf.lua

5.2、跨机器同步

配置:/etc/lsyncd/lsyncd.conf.lua

Lua 复制代码
-- settings 表用于定义全局设置
settings {
   logfile    = "/var/log/lsyncd/lsyncd.log",
   statusFile = "/var/log/lsyncd-status.log",
   inotifyMode = "CloseWrite or Modify",
   statusInterval = 20,                  
   maxProcesses = 1,  
   nodaemon   = false        
}


-- sync 表用于定义同步任务
sync {
    default.rsync,
    source = "/home/gc/lsyncd/source/",
    target = "gc@10.68.250.14:/home/gc/lsyncd/dest/",
    delay = 5,
    delete = true,
   
    rsync = {
        binary = "/usr/bin/rsync",
        archive = true,
        compress = true,
        verbose = true
    }
}

先建议前台运行检查配置是否正确: lsyncd -nodaemon /etc/lsyncd/lsyncd.conf.lua

报错1:

原因: rsync 权限不足:目标端用户 gc@10.68.250.13 对 /home/gc/lsyncd/dest/ 目录没有写权限
方案:
sudo chown gc:gc /home/gc/lsyncd/dest # 将目录所有者改为 gc

注意事项

问1:这个大文件夹里的数据也在持续的更新, rsync 命令行手动全量同步会出问题吗?
**答:**会有问题。如果在持续写入的目录上执行 rsync 手动全量同步,很可能导致同步结果不一致、数据丢失或重复同步。
rsync 执行全量同步通常分两步:

  1. 扫描阶段:遍历源目录,构建文件列表(包括文件名、大小、mtime 等元数据)。这一步可能耗时较长,尤其是大目录。
  2. 传输阶段:根据扫描结果,逐个文件比对并传输。

问题根源:从扫描开始到传输结束,源目录一直在变化。rsync 不会对文件系统做"原子快照",因此会错过或错误处理扫描过程中发生的变更。
手动 rsync + 后续 Lsyncd 仅适用于源目录在 rsync 期间完全静止的场景(例如停机维护、数据库备份完成后的导出目录)。如果数据持续更新,不要使用这种组合。
最佳方案:直接使用 Lsyncd 的 init = true(原生支持动态数据)
Lsyncd 设计之初就考虑了这种场景。当设置 init = true 时:

  1. Lsyncd 启动后立即注册 inotify 监听,所以后续所有事件都不会丢失。
  2. 然后Lsyncd 执行一次 rsync 全量同步(相当于手动 rsync 的作用)。
  3. 在全量同步过程中,inotify 持续收集新的文件事件,存入队列。
  4. 全量同步完成后,Lsyncd 会再次处理队列中累积的事件,把刚刚同步期间发生变化的部分再同步一次

问2:default.direct 、default.rsync、default.rsyncssh,这三种同步模式的核心区别
Lsyncd 提供的三种核心同步模式 default.direct、default.rsync 和 default.rsyncssh,本质区别在于底层传输机制、适用场景(本地/远程)以及对文件属性的保留能力。

如何选择?

  • 仅本地同步:优先 default.direct(足够快且简单)或 default.rsync(需要完整属性保留时)。
  • 局域网内远程同步(信任网络):用 default.rsync,省去加密开销,速度快。
  • 跨互联网远程同步:必须用 default.rsyncssh,保证数据安全。
  • 需要断点续传/带宽限制/校验和:任何情况都选 rsync 系列(rsync 或 rsyncssh),因为 direct 不支持这些特性。

性能

lsyncd -nodaemon /etc/lsyncd/lsyncd.conf.lua
数据解读:

top -o %MEM # 按内存百分比降序
top -o %CPU # 按 CPU 使用率降序

首次全量同步后,cpu利用率就下来了

同时监控 lsyncd 和所有 rsync 进程

top -p (pgrep -x "lsyncd\|rsync" \| tr '\\n' ',' \| sed 's/,//')

没有数据传输时:

相关推荐
孙克旭_1 年前
day036-lsyncd实时同步服务与网站存储架构
linux·运维·架构·lsyncd