lsync
参考文档 🍼
背景介绍 🥓
业务中有一个需求是需要将业务数据做同步:网络环境A中的Source机器A 需要通过公网传输的方式 同步文件到网络环境B中的target机器B,现在的实现方式是通过git的方式同步这些数据,但是由于数据量比较大,每过段时间就需要做git gc,并且偶尔会出现更改10M左右的文件但是同步文件100多M。所以需要探索一个新的实现文件同步的方式。
我们基于业务需求对于文件同步考虑到的场景如下:
- 同步多个文件
- 一个Source和多个Target同步
- 同步文件时设置include和exclude
- CPU消耗
- 磁盘消耗
- 跨公网传输时的网络消耗
- 定时同步
着重关注 🥖
跨公网传输文件过程中的网络带宽和CPU资源消耗
简单介绍
Lsyncd 是一种轻量级的实时镜像解决方案,它相对容易安装,不需要新的文件系统或块设备,并且不会影响本地文件系统的性能。
Lsyncd 监视本地目录树事件监视器接口(inotify 或 fsevents)。它会聚合和组合事件几秒钟,然后生成一个(或多个)进程来同步更改。
Lsyncd支持本地-本地/远程的同步方式,支持一个Source和多个Target同步,同步多个Source,同步时设置过滤器 (include要同步的文件、exclude要同步的文件、匹配要同步的文件)等功能。
Lsyncd提供的功能(基于2.3.0版本):
- 本地Source Target同步
- 本地Source-Target远程同步
- 同步时初始化远程目录
- 同步时设置过滤器 include要同步的文件、exclude要同步的文件、匹配要同步的文件
- 同一个Source文件多个Target文件
- inotify侦听的更改类型:Modify,CloseWrite,CloseWrite or Modify
- 隧道:生成多个连接并在它们之间对连接进行负载均衡
- 控制同步的频率:delay
- 定时完全同步
- 高级onAction:定制化编码
实现原理 💅
default.direct(本地文件同步):使用cp、rm等命令来完成差异文件的备份。当源目录中的文件被添加、修改或删除时,lsyncd会根据配置的规则,将这些变化应用到目标目录中。
default.rsync(本地-本地/远程文件同步)::inotify 或 fsevents监视文件的改动,通过rsync中的ssh协议方式传输到Target机器。SSH(Secure Shell)是一种用于远程登录和安全文件传输的网络协议。它提供了加密的数据传输和身份验证机制,确保了远程通信的安全性。
default.rsyncssh(本地-远程文件同步) :inotify 或 fsevents监视文件的改动,通过rsync中的ssh协议方式传输到Target机器。SSH(Secure Shell)是一种用于远程登录和安全文件传输的网络协议。它提供了加密的数据传输和身份验证机制,确保了远程通信的安全性。default.rsyncssh与default.rsync的不同之处在于,它使用 ssh 命令在目标主机上本地移动文件或目录,而不是再次删除和传输。
实现流程 📛
Lsyncd同步时的方式:
- default.direct 本地文件同步
- default.rsync 本地-本地/远程文件同步
- default.rsyncssh 本地-远程文件同步
说明:default.rsyncssh与default.rsync的不同之处在于,它使用 ssh 命令在目标主机上本地移动文件或目录,而不是再次删除和传输。
Lsyncd同步流程如下:
inotify 或 fsevents监视文件的改动
触发rsync增量同步(通过算法获取Source和Target不同的文件信息)
将Source中差异的信息 增量 到Target中
此过程只会传输差异的数据,不会因为两个文件之间存在一丝差异便将整个文件重新传输。
环境介绍 🏞️
该环境为测试环境,并且只为测试安装lsyncd,与下面提到的"实验过程"并不是同一套环境
IP地址 | hostname | role | 操作系统 | 安装软件 |
---|---|---|---|---|
10.0.0.16 | source | Source | Ubuntu 20.04.4 LTS arm64 | lsyncd,rsync |
10.0.0.17 | target | Target | Ubuntu 20.04.4 LTS arm64 | rsync |
安装过程 📷
更换国内源(Source&Target机器操作)
sudo cp /etc/apt/sources.list /etc/apt/sources.list_backup
sudo vim /etc/apt/sources.list
删除原有的内容,添加以下:
# 默认注释了源码仓库,如有需要可自行取消注释
deb https://mirrors.ustc.edu.cn/ubuntu-ports/ focal main restricted universe multiverse
# deb-src https://mirrors.ustc.edu.cn/ubuntu-ports/ focal main main restricted universe multiverse
deb https://mirrors.ustc.edu.cn/ubuntu-ports/ focal-updates main restricted universe multiverse
# deb-src https://mirrors.ustc.edu.cn/ubuntu-ports/ focal-updates main restricted universe multiverse
deb https://mirrors.ustc.edu.cn/ubuntu-ports/ focal-backports main restricted universe multiverse
# deb-src https://mirrors.ustc.edu.cn/ubuntu-ports/ focal-backports main restricted universe multiverse
deb https://mirrors.ustc.edu.cn/ubuntu-ports/ focal-security main restricted universe multiverse
sudo apt-get update
sudo apt-get upgrade
安装lsyncd(Source机器操作)
官方手册中注明的依赖项
- Lua >= 5.2 Lsyncd 依赖于 Lua 5.2 或更高版本;即 5.2 或 5.3。对于大多数发行版,您需要安装 liblua??, liblua??-dev 和 lua??包,带有??是相应的 Lua 版本。
- cmake >= 2.8 要将 Lsyncd 配置到您的系统,需要 cmake >= 2.8
- rsync >= 3.1 在运行时,Lsyncd 需要在源系统和目标系统上安装 rsync > 3.1。
apt安装
apt install -y lsyncd liblua5.3-0 liblua5.3-dev lua5.3 cmake rsync g++
lsyncd --version
编译安装
apt install -y liblua5.3-0 liblua5.3-dev lua5.3 cmake rsync g++
git clone -b v2.3.0 https://github.com/lsyncd/lsyncd.git
cd lsyncd
cmake .
make
make install
创建sourcedir(Source机器)
mkdir /root/sourcedir
创建targetdir(Target机器)
mkdir /root/targetdir
创建配置文件
mkdir /etc/lsyncd /var/log/lsyncd
vim /etc/lsyncd/lsyncd.conf.lua
settings {
logfile = "/var/log/lsyncd/lsyncd.log",
statusFile = "/var/log/lsyncd/lsyncd.status",
statusInterval = 20,
nodaemon = false
}
sync {
default.rsync,
source = "/etc/",
target = "/mnt"
}
systemctl restart lsyncd
systemctl enable lsyncd
systemctl status lsyncd
配置解释 👔
settings {
logfile = "/tmp/lsyncd.log", #日志文件
statusFile = "/tmp/lsyncd.status",#状态报告文件
nodaemon = true, #守护程序,true代表不启用守护程序
}
rsyncssh模式 🇳🇵
设置免密登录(Source机器配置)
ssh-keygen -t rsa
ssh-copy-id root@10.0.0.17
配置lsyncd(Source机器配置)
mkdir /etc/lsyncd /var/log/lsyncd
vim /etc/lsyncd/lsyncd.conf.lua
settings {
logfile = "/var/log/lsyncd/lsyncd.log",
statusFile = "/var/log/lsyncd/lsyncd.status",
statusInterval = 20,
maxDelays = 10,
maxProcesses = 1,
nodaemon = false
}
sync {
default.rsyncssh,
source = "/root/sourcedir/",
host = "root@10.0.0.17",
targetdir = "/root/targetdir/",
rsync = {
binary = "/usr/bin/rsync",
archive = true,
compress = false,
owner = true,
perms = true
},
ssh = {
port = 22
}
}
systemctl restart lsyncd
systemctl enable lsyncd
systemctl status lsyncd
传输过程中资源消耗 🤓
实验目的 📰
需要说明下实验的目的:并不是为了贴近生产环境,生产环境中修改的文件数量和Source Target数量都是不一样的,没有环境可以模拟。
实验的目的是传输一定量的文件,查看Source机器的资源消耗,得出传输过程中那些资源限制了lsyncd的传输速率。
实验环境 🔍
基于公司真实环境进行实验,数据已经做了脱敏处理
IP地址 | hostname | role | 操作系统 | 安装软件 |
---|---|---|---|---|
Xxx | vm09 | Source | CentOS Linux 7 (Core) | lsyncd、rsync |
Xxx | jiangm01 | Target | Debian GNU/Linux 11 (bullseye) | rsync |
Xxx | dongg02 | Target | CentOS Linux 7 (Core) | rsync |
Xxx | dongg03 | Target | Debian GNU/Linux 11 (bullseye) | rsync |
环境准备 🔎
设置免密(实际环境中已经做好了免密,此步骤属于示例)
ssh-keygen -t rsa
ssh-copy-id root@jiangm01
ssh-copy-id root@dongg02
ssh-copy-id root@dongg03
下载lsyncd
yum install -y lsyncd liblua5.3-0 liblua5.3-dev lua5.3 cmake rsync g++
lsyncd --version
which rsync
结论 🀄
说明:真实应用场景是文件的修改,但是为考虑到更好的统计出同步的延迟时间,采用add file的方式进行测试,这种测试方式的压力会比修改文件内容更大,所以修改文件的情况下 Source端的压力更小。
参考原理:rsync算法原理及使用 - 知乎 (zhihu.com)
因为是一个Source多个Target的同步方式,我们着重关注Source机器的资源消耗
模拟场景:每秒添加一个文件,共添加150个文件。
每文件大小30M | 每个文件大小64KB | |
---|---|---|
rsyncssh模式(进程数量1) | CPU消耗:%3->18% 网络消耗:0->150Mb 延迟情况:26、39、7;完全同步时间:17:16:29 - 17:01:53 | CPU消耗:几乎不变 网络消耗:几乎不变 延迟情况:忽略不计完全同步时间:几乎完全同步 |
rsync模式(进程数量100) | CPU消耗:3%->33% 网络消耗:0->200Mb 延迟情况:70、30、29完全同步时间:17:48:09 - 17:35:30 | CPU消耗:几乎不变 网络消耗:几乎不变 延迟情况:忽略不计完全同步时间:几乎完全同步 |
rsync模式(进程数量1) | CPU消耗:2%->15% 网络消耗:0->150Mb 延迟情况:15、0、0 完全同步时间:11:20:20 - 11:05:56 | CPU消耗:几乎不变 网络消耗:几乎不变 延迟情况:忽略不计完全同步时间:几乎完全同步 |
解释:
- CPU消耗:没启动lsyncd时的CPU资源->启动lsyncd后消耗最大CPU资源值
- 网络消耗:没启动lsyncd时的网络资源->启动lsyncd后消耗最大网络资源值
- 延迟情况:Source端完成150文件时 已经同步的到Target文件的数量
- 完全同步时间:Target端同步完毕时的时间- Source端完成150文件的时间
实验过程 ✌️
配置项解释:
statusInterval = 10, # 将lsyncd的状态写入上面的statusFile的间隔,默认10秒
maxDelays = 3,#累计到多少所监控的事件激活一次同步
maxProcesses = 1, #default.rsyncssh必须将maxProcesses设置为1。
nodaemon = false #false表示启用守护进程状态
archive = true, #递归,即同步子目录的内容。
compress = false, #传输过程中压缩文件数据,相对其他压缩工具而言,它可以获得更好的压缩率,但是需要消耗CPU资源。 此处关闭
owner = true, #保持属主
perms = true # 默认保留文件权限。
模拟大文件
cd /root/sync/sync/black
# du -sh 5-atl3-BLACK_LIST_SYNC_DATA.txt
30M 5-atl3-BLACK_LIST_SYNC_DATA.txt
for num in $(seq 150) ; do cp 5-atl3-BLACK_LIST_SYNC_DATA.txt test_$num.txt && sleep 1; done && date
模拟小文件
cd /root/sync/sync/black
# du -sh 6-atl2-BLACK_LIST_SYNC_DATA.txt
64K 6-atl2-BLACK_LIST_SYNC_DATA.txt
for num in $(seq 150) ; do cp 6-atl2-BLACK_LIST_SYNC_DATA.txt test_$num.txt && sleep 1; done && date
rsyncssh模式 🌵
配置文件
settings {
logfile = "/var/log/lsyncd/lsyncd.log",
statusFile = "/var/log/lsyncd/lsyncd.status",
statusInterval = 10,
maxDelays = 3,
maxProcesses = 1,
nodaemon = false
}
sync {
default.rsyncssh,
source = "/root/sync/sync",
host = "root@jiangm01",
targetdir = "/root/targetdir/",
rsync = {
binary = "/usr/bin/rsync",
archive = true,
compress = false,
owner = true,
perms = true
},
ssh = {
port = 22
}
}
sync {
default.rsyncssh,
source = "/root/sync/sync",
host = "root@dongg02",
targetdir = "/root/targetdir/",
rsync = {
binary = "/usr/bin/rsync",
archive = true,
compress = false,
owner = true,
perms = true
},
ssh = {
port = 22
}
}
sync {
default.rsyncssh,
source = "/root/sync/sync",
host = "root@dongg03",
targetdir = "/root/targetdir/",
rsync = {
binary = "/usr/bin/rsync",
archive = true,
compress = false,
owner = true,
perms = true
},
ssh = {
port = 22
}
}
大文件
传输前Source机器资源情况
启动lsyncd
systemctl restart lsyncd
systemctl enable lsyncd
systemctl status lsyncd
传输中Source机器资源情况
小文件
传输前Source机器资源情况
启动lsyncd
systemctl restart lsyncd
systemctl enable lsyncd
systemctl status lsyncd
传输中Source机器资源情况
rsync模式 🤙
配置文件
settings {
logfile = "/var/log/lsyncd/lsyncd.log",
statusFile = "/var/log/lsyncd/lsyncd.status",
statusInterval = 10,
maxDelays = 1,
maxProcesses = 100,
nodaemon = false
}
sync {
default.rsync,
source = "/root/sync/sync",
target = "root@jiangm01:/root/targetdir/",
rsync = {
binary = "/usr/bin/rsync",
archive = true,
compress = false,
owner = true,
perms = true
}
}
sync {
default.rsync,
source = "/root/sync/sync",
target = "root@dongg02:/root/targetdir/",
rsync = {
binary = "/usr/bin/rsync",
archive = true,
compress = false,
owner = true,
perms = true
}
}
sync {
default.rsync,
source = "/root/sync/sync",
target = "root@dongg03:/root/targetdir/",
rsync = {
binary = "/usr/bin/rsync",
archive = true,
compress = false,
owner = true,
perms = true
}
}
进程100大文件
传输前Source机器资源情况
启动lsyncd
systemctl restart lsyncd
systemctl enable lsyncd
systemctl status lsyncd
传输中Source机器资源情况
进程100小文件
传输前Source机器资源情况
启动lsyncd
systemctl restart lsyncd
systemctl enable lsyncd
systemctl status lsyncd
传输中Source机器资源情况
进程1大文件
传输前Source机器资源情况
启动lsyncd
systemctl restart lsyncd
systemctl enable lsyncd
systemctl status lsyncd
传输中Source机器资源情况
进程1小文件
传输前Source机器资源情况
启动lsyncd
systemctl restart lsyncd
systemctl enable lsyncd
systemctl status lsyncd
传输中Source机器资源情况
lsyncd的增量传输 🍰
实验目的 🍥
验证lsyncd传输的是整个文件还是仅仅被改动的字符串? 比如我有一个1G的文件 我向这个文件中增加了10M的文字,lsyncd传输1G+10M还是传输10M的内容?
判断方式:通过监控网络流量的方式 来确定lsyncd的传输方式
实验环境 📲
IP地址 | hostname | role | 操作系统 | 安装软件 |
---|---|---|---|---|
xxx | vm09 | Source | CentOS Linux 7 (Core) | lsyncd、rsync |
xxx | jiangm01 | Target | Debian GNU/Linux 11 (bullseye) | rsync |
xxx | dongg02 | Target | CentOS Linux 7 (Core) | rsync |
xxx | dongg03 | Target | Debian GNU/Linux 11 (bullseye) | rsync |
lsyncd的模式:rsync
生成1G文件的方式
# 找一个10M左右的文件 循环cat 添加一定次数,得到1G左右的1.json
for i in $(seq 100); do cat A_SYNC_MSG.json >> 1.json; done
添加10M
# 找一个10M左右的文件 cat 4-atl3-BLACK_LIST_SYNC_DATA.txt >> 1.json
cat 4-atl3-BLACK_LIST_SYNC_DATA.txt >> 1.json
实验过程 🐫
传输1G初始文件时监控图表
传输添加10M文件时的监控图表
实验结论 ⏰
lsyncd传输的只是差异的内容,并不会将整个文件重新传输。
lsyncd的网络带宽限制 🌖
实验目的 🚶
限制lsyncd传输数据过程中的网络带宽消耗
实验环境 🚶♀️
IP地址 | hostname | role | 操作系统 | 安装软件 |
---|---|---|---|---|
xxx | vm09 | Source | CentOS Linux 7 (Core) | lsyncd、rsync |
xxx | jiangm01 | Target | Debian GNU/Linux 11 (bullseye) | rsync |
xxx | dongg02 | Target | CentOS Linux 7 (Core) | rsync |
xxx | dongg03 | Target | Debian GNU/Linux 11 (bullseye) | rsync |
lsyncd的模式:rsync
实验过程 🍉
限制网络带宽
生成文件
cd /root/sync/sync/black
# du -sh 5-atl3-BLACK_LIST_SYNC_DATA.txt
30M 5-atl3-BLACK_LIST_SYNC_DATA.txt
for num in $(seq 150) ; do cp 5-atl3-BLACK_LIST_SYNC_DATA.txt test_$num.txt && sleep 1; done && date
配置文件
settings {
logfile = "/var/log/lsyncd/lsyncd.log",
statusFile = "/var/log/lsyncd/lsyncd.status",
statusInterval = 10,
maxDelays = 1,
maxProcesses = 1,
nodaemon = false
}
sync {
default.rsync,
source = "/root/sync/sync",
target = "root@jiangm01:/root/targetdir/",
rsync = {
binary = "/usr/bin/rsync",
bwlimit = 1000,
archive = true,
compress = false,
owner = true,
perms = true
}
}
sync {
default.rsync,
source = "/root/sync/sync",
target = "root@dongg02:/root/targetdir/",
rsync = {
binary = "/usr/bin/rsync",
bwlimit = 1000,
archive = true,
compress = false,
owner = true,
perms = true
}
}
sync {
default.rsync,
source = "/root/sync/sync",
target = "root@dongg03:/root/targetdir/",
rsync = {
binary = "/usr/bin/rsync",
bwlimit = 1000,
archive = true,
compress = false,
owner = true,
perms = true
}
}
网络带宽不做限制
配置文件
settings {
logfile = "/var/log/lsyncd/lsyncd.log",
statusFile = "/var/log/lsyncd/lsyncd.status",
statusInterval = 10,
maxDelays = 1,
maxProcesses = 1,
nodaemon = false
}
sync {
default.rsync,
source = "/root/sync/sync",
target = "root@jiangm01:/root/targetdir/",
rsync = {
binary = "/usr/bin/rsync",
archive = true,
compress = false,
owner = true,
perms = true
}
}
sync {
default.rsync,
source = "/root/sync/sync",
target = "root@dongg02:/root/targetdir/",
rsync = {
binary = "/usr/bin/rsync",
archive = true,
compress = false,
owner = true,
perms = true
}
}
sync {
default.rsync,
source = "/root/sync/sync",
target = "root@dongg03:/root/targetdir/",
rsync = {
binary = "/usr/bin/rsync",
archive = true,
compress = false,
owner = true,
perms = true
}
}
实验结论 🌾
添加bwlimit参数可以有效限制网络带宽的消耗。