摘要:本文深入解析 rsync 的增量传输原理(rolling checksum 算法),详解常用参数组合与避坑技巧,并通过代码部署、服务器备份、多机同步等实战场景展示 rsync 的高效用法,最后给出性能调优建议与常见问题解决方案。

每次部署 项目 ,把几个 GB 的 dist 目录传到服务器上,等 scp 慢悠悠地全量传输,我都想砸键盘。直到认真研究了 rsync 的增量传输算法,才发现这玩意儿有多香——同样是同步 2GB 的目录,改了 3 个文件,rsync 只传那几 KB 的差异。

rsync 的增量传输原理

rsync 的核心是一个叫 rolling checksum(滚动校验)的算法。它不会傻乎乎地把整个文件传过去,而是这样工作的:

  1. 把目标文件按固定大小分块(默认 700 字节)
  2. 对每个块计算两个校验值:一个弱校验(Adler-32 变体),一个强校验(MD4/MD5)
  3. 源文件也按同样方式分块,逐块比较
  4. 只传输有差异的块

关键在于弱校验是滚动计算的——窗口滑动一个字节就能算出新值,不需要重新计算整个块。这意味着比较的复杂度是 O(n),不是 O(n×m)。

# 最基础的同步:本地到远程
rsync -avz ./project/ user@server:/var/www/project/

# 参数解释:
# -a  归档模式,保留权限、时间戳、符号链接等
# -v  显示详细输出
# -z  传输时压缩数据

参数组合的讲究

rsync 的参数组合很多,踩过坑才知道该怎么搭配。

必知参数

# --delete:删除目标端多余的文件,保持完全一致
rsync -avz --delete ./src/ user@server:/var/www/src/

# --exclude:排除不需要同步的文件
rsync -avz --exclude='node_modules' --exclude='.git' ./project/ user@server:/opt/project/

# --progress:显示传输进度和速度
rsync -avz --progress ./large-file.tar.gz user@server:/backup/

# --bwlimit:限速,防止占满带宽
rsync -avz --bwlimit=5000 ./data/ user@server:/backup/data/
# 5000 表示 5000KB/s,约 5MB/s

源路径末尾斜杠的坑

这个坑很多人踩过:

# 有末尾斜杠:复制目录下的内容到目标
rsync -avz /data/logs/ /backup/logs/
# 结果:/backup/logs/ 下有 logs 里的文件

# 无末尾斜杠:复制整个目录到目标下
rsync -avz /data/logs /backup/logs/
# 结果:/backup/logs/logs/ 下有文件

记住:有斜杠复制内容,无斜杠复制目录本身。

delta-transfer 算法详解

rsync 的 -c 参数会改变校验策略:

# 默认模式:比较文件大小和修改时间(快速)
rsync -avz ./src/ user@server:/dst/

# 校验模式:比较文件内容校验和(慢但精确)
rsync -avzc ./src/ user@server:/dst/

默认模式有时会误判——比如你 touch 了一个文件但没改内容,rsync 认为文件变了会重新传。加上 -c 就会计算校验和,只传真正变化的。对于大文件场景,这个选项能省很多流量。

–partial: 断点 续传

网络不稳定时,大文件传到一半断了很常见:

# --partial:保留部分传输的文件,下次从断点继续
rsync -avz --partial --progress ./big-file.iso user@server:/iso/

# --partial-dir:指定部分文件存放位置(更整洁)
rsync -avz --partial-dir=.rsync-partial ./big-file.iso user@server:/iso/

实战场景

1. 代码部署(本地→服务器)

#!/bin/bash
# deploy.sh - 一键部署脚本
RSYNC_OPTS="-avz --delete --exclude='.git' --exclude='node_modules' --exclude='.env.local'"
REMOTE="deploy@prod-server:/var/www/app"

echo "Deploying to production..."
rsync $RSYNC_OPTS ./dist/ $REMOTE/dist/
rsync $RSYNC_OPTS ./package.json $REMOTE/
rsync $RSYNC_OPTS ./ecosystem.config.js $REMOTE/

echo "Restarting service..."
ssh deploy@prod-server "cd /var/www/app && npm install --production && pm2 restart ecosystem.config.js"

2. 服务器备份(远程→本地)

# 全量备份(首次)
rsync -avz user@server:/data/ /backup/server-data/

# 增量备份(后续):只传输变化的文件
rsync -avz --delete --backup --backup-dir=/backup/incremental/$(date +%Y%m%d) \
  user@server:/data/ /backup/server-data/

# --backup-dir 把被删除或覆盖的文件存到指定目录
# 实现了"增量备份"效果:当前目录是最新状态,backup-dir 是历史版本

3. 多服务器同步

# 从主服务器同步到多台从服务器
for host in slave1 slave2 slave3; do
  rsync -avz --delete -e ssh /data/shared/ ${host}:/data/shared/
  echo "Synced to $host"
done

性能调优

并行传输

rsync 本身是单连接传输,但可以配合 GNU parallel :

# 并行同步多个目录
find /data -maxdepth 1 -type d | parallel -j 4 rsync -avz {} user@server:/backup/

压缩级别

# -z 默认压缩级别,对于已压缩的文件(zip、mp4)反而更慢
# 可以用 --skip-compress 跳过已压缩格式
rsync -avz --skip-compress=gz/zip/mp4/jpg/png ./mixed-files/ user@server:/backup/

大文件特殊处理

# 对大文件使用 inotify 监控变化部分
# --inplace:直接在目标文件上修改,不创建临时文件
# 适合数据库文件等不能中断的场景
rsync -avz --inplace --no-whole-file ./db/ user@server:/backup/db/

常见问题

问题原因解决方案
权限报错目标目录无写权限加 --chmod 或用 sudo
证书认证失败SSH 密钥未配置加 -e “ssh -i ~/.ssh/key”
大量小文件慢文件数太多,建连开销大先 tar 打包再传
符号链接丢失默认不跟随符号链接加 -L 跟随或 -l 保留
中文文件名乱码字符集不一致加 --iconv=utf-8

rsync 是那种"用了就回不去"的工具。它不是最简单的,但增量传输算法让它在大量文件同步场景下无可替代。更多 rsync 的参数和用法,可以试试 rsync 在线速查


相关工具:SCP 安全复制 | SSH 远程登录
在这里插入图片描述


1 声望0 粉丝