1. 远程文件同步的常见方式:
1,cron + rsync
优点: 简单
缺点: 定时执行, 实时性比较差; 另外, rsync 同步数据时, 需要扫描所有文件后进行比对, 进行差量传输. 如果文件数量达到了百万甚至千万量级, 扫描所有文件将是非常耗时的. 远程对比时发送所有的文件树 or 目录树属性, 而且正在发生变化的往往是其中很少的一部分, 这是非常低效的方式.
2. inotify + rsync
优点: 比较简单
缺点: 每个变更文件都使用了 rsync. 而每一次 rsync 都要建立 SSH 链接, 这个其实是比较费时间的. 文件频繁更新会产生不必要的 rsync, 进程 or 线程, 比如不支持批量定时同步等.
3. lsyncd (python 版本叫 inosync)
优点: 实时性高, 速率可控, 兼容了 rsync 协议, 以及 lua 语言的灵活高效.
缺点: 需要了解 inotify,rsync 的原理, 运用, 需要多引入一个 lua, 定制业务稍复杂.
4. Linux watchdog 事件监控文件
缺点: 过于底层
5. 使用 sersync , lipsync 等类似工具
缺点: 不利于统一标准运维, 可自行研究
2. 几大实时同步工具比较
2.1 inotify + rsync
最近一直在寻求生产服务服务器上的同步替代方案, 原先使用的是 inotify + rsync, 但随着文件数量的增大到 100W+, 目录下的文件列表就达 20M, 在网络状况不佳或者限速的情况下, 变更的文件可能 10 来个才几 M, 却因此要发送的文件列表就达 20M, 严重减低的带宽的使用效率以及同步效率; 更为要紧的是, 加入 inotifywait 在 5s 内监控到 10 个小文件发生变化, 便会触发 10 个 rsync 同步操作, 结果就是真正需要传输的才 2-3M 的文件, 比对的文件列表就达 200M. 使用这两个组合的好处在于, 它们都是最基本的软件, 可以通过不同选项做到很精确的控制, 比如排除同步的目录, 同步多个模块或同步到多个主机.
搭建过程参考 Linux 下同步工具 inotify+rsync 使用详解 http://seanlook.com/2014/12/12/rsync_inotify_setup/ .
2.2 sersync2
后来听同事说 sersync http://www.ccvita.com/422.html 这么个工具可以提高同步的性能, 也解决了同步大文件时出现异常的问题, 所以就尝试了一下. sersync 是国内的一个开发者开源出来的, 使用 c++ 编写, 采用多线程的方式进行同步, 失败后还有重传机制, 对临时文件过滤, 自带 crontab 定时同步功能. 网上看到有人说性能还不错, 说一下我的观点:
国产开源, 文档不是很全, 在 2011 年之后就没更新了(googlecode 都要快关闭了, 其实可以转交其他人维护), 网上关于它的使用和讨论都止于 10 年了
采用 xml 配置文件的方式, 可读性比较好, 但是有些原生的有些功能没有实现就没法使用了
无法实现多目录同步, 只能通过多个配置文件启动多个进程
文件排除功能太弱. 这个要看需求, 不是每个人都需要排除子目录. 而对于我的环境中, 这个功能很重要, 而且排除的规则较多
虽然提供插件的功能, 但很鸡肋, 因为软件本身没有持续更新, 也没有看到贡献有其它插件出现(可能是我知识面不够, 还用不到里面的 refreshCDN plugin).
只要执行 rsync 命令, 就会对整个目录进行遍历, 发送要比对的文件列表, 然后再发送变化的文件. sersync 只是减少了监听的事件, 减少了 rsync 的次数 -- 这已经是很大的改进, 但每次 rsync 没办法改变. 目前使用 sersync2 没什么问题, 而且看了它的设计思路应该是比较科学的, 特别是过滤队列的设计. 双向同步看起来也是可以实现, 只是使用的不多.
2.3 lsyncd
废话说这么多, 本文就是介绍它了. 有些博客说 lsyncd 是谷歌开源的, 实际不是了, 只是托管在了 googlecode 上而已, 幸运的是已经迁移到 github 了: https://github.com/axkibe/lsyncd .
Lysncd 实际上是 lua 语言封装了 inotify 和 rsync 工具, 采用了 Linux 内核 (2.6.13 及以后) 里的 inotify 触发机制, 然后通过 rsync 去差异同步, 达到实时的效果. 我认为它最令人称道的特性是, 完美解决了 inotify + rsync 海量文件同步带来的文件频繁发送文件列表的问题 -- 通过时间延迟或累计触发事件次数实现. 另外, 它的配置方式很简单, lua 本身就是一种配置语言, 可读性非常强. lsyncd 也有多种工作模式可以选择, 本地目录 cp, 本地目录 rsync, 远程目录 rsynCSSh.
实现简单高效的本地目录同步备份(网络存储挂载也当作本地目录), 一个命令搞定.
3. 使用 lsyncd 本地目录实时备份
这一节实现的功能是, 本地目录 source 实时同步到另一个目录 target, 而在 source 下有大量的文件, 并且有部分目录和临时文件不需要同步.
3.1 安装 lsyncd
安装 lsyncd 极为简单, 已经收录在 ubuntu 的官方镜像源里, 直接通过
apt-get install lsyncd
就可以.
在 Redhat 系, 可以手动去下载安装, 但首先你得安装两个依赖
yum install lua lua-devel
. 也可以通过在线安装, 需要 epel-release 扩展包:
# yum install lsyncd
源码编译安装
从源码编译安装可以使用最新版的 lsyncd 程序, 但必须要相应的依赖库文件和编译工具:
- yum install lua lua-devel asciidoc cmake
- .
从 googlecode lsyncd http://code.google.com/p/lsyncd/downloads/list 上下载的 lsyncd-2.1.5.tar.gz, 直接./configure,
make && make install
就可以了.
从 github 上下载 lsyncd-master.zip https://github.com/axkibe/lsyncd/archive/master.zip 的 2.1.5 版本使用的是 cmake 编译工具, 无法./configure:
- # uzip lsyncd-master.zip
- # cd lsyncd-master
- # cmake -DCMAKE_INSTALL_PREFIX=/usr/local/lsyncd-2.1.5
- # make && make install
我这个版本编译时有个小 bug, 如果按照 INSTALL 在 build 目录中 make, 会提示:
- [100%] Generating doc/lsyncd.1
- Updating the manpage
a2x: failed: source file not found: doc/lsyncd.1.txt
- make[2]: *** [doc/lsyncd.1] Error 1
- make[1]: *** [CMakeFiles/manpage.dir/all] Error 2
- make: *** [all] Error 2
解决办法是要么直接在解压目录下 cmake, 不要 mkdir build, 要么在 CMakeList.txt 中搜索 doc 字符串, 在前面加上
- ${PROJECT_SOURCE_DIR}
- .
- 3.2 lsyncd.conf
下面都是在编译安装的情况下操作.
3.2.1 lsyncd 同步配置
- # cd /usr/local/lsyncd-2.1.5
- # mkdir etc var
- # vi etc/lsyncd.conf
- settings {
- logfile ="/usr/local/lsyncd-2.1.5/var/lsyncd.log",
- statusFile ="/usr/local/lsyncd-2.1.5/var/lsyncd.status",
- inotifyMode = "CloseWrite",
- maxProcesses = 7,
- -- nodaemon =true,
- }
- sync {
- default.rsync,
- source = "/tmp/src",
- target = "/tmp/dest",
- -- excludeFrom = "/etc/rsyncd.d/rsync_exclude.lst",
- rsync = {
- binary = "/usr/bin/rsync",
- archive = true,
- compress = true,
- verbose = true
- }
- }
到这启动 lsycnd 就可以完成实时同步了, 默认的许多参数可以满足绝大部分需求, 非常简单.
3.2.2 lsyncd.conf 配置选项说明
settings
里面是全局设置,-- 开头表示注释, 下面是几个常用选项说明:
logfile 定义日志文件
stausFile 定义状态文件
nodaemon=true 表示不启用守护模式, 默认
statusInterval 将 lsyncd 的状态写入上面的 statusFile 的间隔, 默认 10 秒
inotifyMode 指定 inotify 监控的事件, 默认是 CloseWrite, 还可以是 Modify 或
CloseWrite or Modify
maxProcesses 同步进程的最大个数. 假如同时有 20 个文件需要同步, 而 maxProcesses = 8, 则最大能看到有 8 个 rysnc 进程
maxDelays 累计到多少所监控的事件激活一次同步, 即使后面的 delay 延迟时间还未到
sync
里面是定义同步参数, 可以继续使用 maxDelays 来重写 settings 的全局变量. 一般第一个参数指定 lsyncd 以什么模式运行: rsync,rsyncssh,direct 三种模式:
default.rsync : 本地目录间同步, 使用 rsync, 也可以达到使用 ssh 形式的远程 rsync 效果, 或 daemon 方式连接远程 rsyncd 进程;
default.direct : 本地目录间同步, 使用 cp,rm 等命令完成差异文件备份;
default.rsyncssh : 同步到远程主机目录, rsync 的 ssh 模式, 需要使用 key 来认证
source 同步的源目录, 使用绝对路径.
target 定义目的地址. 对应不同的模式有几种写法:
/tmp/dest : 本地目录同步, 可用于 direct 和 rsync 模式
172.29.88.223:/tmp/dest
: 同步到远程服务器目录, 可用于 rsync 和 rsyncssh 模式, 拼接的命令类似于
/usr/bin/rsync -ltsd --delete --include-from=- --exclude=* SOURCE TARGET
, 剩下的就是 rsync 的内容了, 比如指定 username, 免密码同步
172.29.88.223::module
: 同步到远程服务器目录, 用于 rsync 模式
三种模式的示例会在后面给出.
init 这是一个优化选项, 当 init = false, 只同步进程启动以后发生改动事件的文件, 原有的目录即使有差异也不会同步. 默认是 true
delay 累计事件, 等待 rsync 同步延时时间, 默认 15 秒(最大累计到 1000 个不可合并的事件). 也就是 15s 内监控目录下发生的改动, 会累积到一次 rsync 同步, 避免过于频繁的同步.(可合并的意思是, 15s 内两次修改了同一文件, 最后只同步最新的文件)
excludeFrom 排除选项, 后面指定排除的列表文件, 如
excludeFrom = "/etc/lsyncd.exclude"
, 如果是简单的排除, 可以使用 exclude = LIST.
这里的排除规则写法与原生 rsync 有点不同, 更为简单:
监控路径里的任何部分匹配到一个文本, 都会被排除, 例如 / bin/foo/bar 可以匹配规则 foo
如果规则以斜线 / 开头, 则从头开始要匹配全部
如果规则以 / 结尾, 则要匹配监控路径的末尾
? 匹配任何字符, 但不包括 /* 匹配 0 或多个字符, 但不包括 /** 匹配 0 或多个字符, 可以是 /
delete 为了保持 target 与 souce 完全同步, Lsyncd 默认会 delete = true 来允许同步删除. 它除了 false, 还有 startup,running 值, 请参考 Lsyncd 2.1.x Layer 4 Config Default Behavior https://github.com/axkibe/lsyncd/wiki/Lsyncd 2.1.x ‖ Layer 4 Config ‖ Default Behavior .
- rsync
- (提示一下, delete 和 exclude 本来都是 rsync 的选项, 上面是配置在 sync 中的, 我想这样做的原因是为了减少 rsync 的开销)
bwlimit 限速, 单位 kb/s, 与 rsync 相同(这么重要的选项在文档里竟然没有标出)
compress 压缩传输默认为 true. 在带宽与 cpu 负载之间权衡, 本地目录同步可以考虑把它设为 false
perms 默认保留文件权限.
其它 rsync 的选项
其它还有 rsyncssh 模式独有的配置项, 如 host,targetdir,rsync_path,password_file, 见后文示例.
rsyncOps={"-avz","--delete"}
这样的写法在 2.1.* 版本已经不支持.
lsyncd.conf 可以有多个 sync, 各自的 source, 各自的 target, 各自的模式, 互不影响.
3.3 启动 lsyncd
使用命令加载配置文件, 启动守护进程, 自动同步目录操作.
lsyncd -log Exec /usr/local/lsyncd-2.1.5/etc/lsyncd.conf
3.4 lsyncd.conf 其它模式示例
以下配置本人都已经过验证可行, 必须根据实际需要裁剪配置:
- settings {
- logfile ="/usr/local/lsyncd-2.1.5/var/lsyncd.log",
- statusFile ="/usr/local/lsyncd-2.1.5/var/lsyncd.status",
- inotifyMode = "CloseWrite",
- 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 = "172.29.88.223:/tmp/dest",
- -- 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",
- -- maxDelays = 5,
- delay = 0,
- -- init = false,
- rsync = {
- binary = "/usr/bin/rsync",
- archive = true,
- compress = true,
- verbose = true,
- _extra = {"--bwlimit=2000"},
- },
- ssh = {
- port = 1234
- }
- }
上面的内容几乎涵盖了所有同步的模式, 其中第 III 个要求像 rsync 一样配置 rsyncd 服务端, 见本文开头. 第 IV,V 配置 ssh 方式同步, 达到的效果相同, 但实际同步时你会发现每次同步都会提示输入 ssh 的密码, 可以通过以下方法解决:
在远端被同步的服务器上开启 ssh 无密码登录, 请注意用户身份:
user$ ssh-keygen -t rsa
一路回车...
user$ cd ~/.ssh
user$ cat id_rsa.pub>> authorized_keys
把 id_rsa 私钥拷贝到执行 lsyncd 的机器上
user$ chmod 600 ~/.ssh/id_rsa
测试能否无密码登录
user$ ssh user@172.29.88.223
4. 高级用法
可以用 lua 灵活 coding:
- module_name = "comos"
- origin_base_dir = "/data1/ms"
- path_list = {
- "/template",
- "/template.test",
- "/resource",
- }
- for _, server in ipairs(target_ip_list) do
- for _, path in ipairs(path_list) do
- print( origin_base_dir..path ,'=>' , server .. "::" .. module_name..path)
- sync {
- default.rsync,
- source = origin_base_dir..path,
target = server .. "::" .. module_name..path ,
- rsync = {
- binary = "/usr/bin/rsync",
- _extra = {"-avuz", "--omit-dir-times","--delay-updates", "--exclude","*.git", "--exclude","*.svn"}
- }
- }
- end
- end
5. lsyncd 的其它功能
lsyncd 的功能不仅仅是同步, 官方手册 Lsyncd 2.1.x Layer 2 Config Advanced onAction https://github.com/axkibe/lsyncd/wiki/Lsyncd 2.1.x ‖ Layer 2 Config ‖ Advanced onAction 高级功能提到, 还可以监控某个目录下的文件, 根据触发的事件自己定义要执行的命令, example 是监控某个某个目录, 只要是有 jpg,gif,png 格式的文件参数, 就把它们转成 pdf, 然后同步到另一个目录. 正好在我运维的一个项目中有这个需求, 现在都是在 java 代码里转换, 还容易出现异常, 通过 lsyncd 可以代替这样的功能. 但, 门槛在于要会一点点 lua 语言(根据官方 example 还是可以写出来).
另外偶然想到个问题, 同时设置了 maxDelays 和 delay, 当监控目录一直没有文件变化了, 也会发生同步操作, 虽然没有可 rsync 的文件.
远程文件同步详解(Remote File Sync)
来源: http://www.bubuko.com/infodetail-2582791.html