资讯动态

云服务器 rsync 同步慢?从带宽到参数的传输优化指南

发布时间:2026/9/16 2:35:21 来源:尧图企业网站定制
1. 项目概述与核心痛点rsync 在云服务器环境里到底卡在哪1.1 rsync 是什么为什么云服务器场景特别需要它rsync 是我日常运维里用得最频繁的一条命令没有之一。它的核心机制是“增量传输”客户端和服务器端先各自把文件切成大小不等的块计算校验值互相交换后只传输有差异的块。所以第二次同步同一批文件时速度可以做到非常快哪怕目录里有几十万个文件。在云服务器场景下rsync 几乎是数据传输的标准答案。你从本地把站点代码推到云上、在两台云服务器之间做数据迁移、把生产库备份拉到本地、或者做异地灾备的镜像同步rsync 都是首选。原因很简单公网带宽是按 Mbps 计费的流量也是钱rsync 能把“重复传”的部分省掉这是 FTP、scp 这类全量拷贝工具做不到的。但问题恰恰出在这里——rsync 在内网和本地上跑得很欢一旦目标换成云服务器很多人就发现“速度上不去”“特别卡”“传一半断了”。这不是 rsync 本身不行而是云服务器的网络环境和本地千兆内网截然不同。如果你拿本地同步的思路直接套到云上踩坑几乎是必然的。1.2 云服务器网络环境与本地内网的本质差异先看三个直接影响 rsync 性能的客观因素。第一公网带宽小。本地千兆内网跑 rsync瓶颈通常不在网络而在磁盘 IO 或 CPU。云服务器的公网带宽一般是 1Mbps、5Mbps、10Mbps 这样的小水管包年包月加的带宽贵得离谱。就算你买的是按流量计费的机器带宽上限也就百兆级别。带宽小了rsync 的增量优势会大打折扣因为大文件的首次同步无论如何都要把它完整传一遍。第二延迟高而且 RTT往返时延不稳定。内网延迟零点几毫秒同城公网 5~10ms跨地域公网 50~100ms 都很常见。TCP 协议在长延迟链路上想跑满带宽对传输窗口要求极高默认的系统参数往往没给你调好。这是“带宽看着不小实际吞吐惨不忍睹”的典型原因。第三公网质量不可控。跨运营商、跨地域传输时丢包、抖动、带宽竞争都会影响 TCP 拥塞控制rsync 的传输效率会大打折扣。拿日常场景打个比方在内网做同步相当于同城快递骑个小电驴一天能送几百单云上同步是跨省物流要考虑路况、天气、车皮容量你还得规划好包裹怎么打包。所以这篇博文的核心就是围绕 rsync 这套“同城快递方案”在云服务器这个“跨省物流”场景下做网络优化改造。2. rsync 核心参数再认知决定同步效率的关键开关很多人用 rsync 就一条命令走天下rsync -avz。这三个参数在本地跑没问题但放到云服务器上-z和-a的组合可能会让同步变得奇慢无比。下面逐个拆解我实际验证过的参数选择和踩坑记录。2.1 压缩参数 -z 的正确打开方式不是所有文件都该压缩-z的作用是在传输前对数据做压缩。它对纯文本类文件日志、JSON、HTML、CSS、源代码收益非常大因为这些文件的压缩率可以到 5:1 甚至更高相当于把带宽“放大”了好几倍。但坑也在这里。如果你同步的目录里有大量图片jpg、png、视频mp4、mkv、压缩包zip、tar.gz、数据库备份文件.sql.gz 之类这些文件本身已经是高度压缩过的格式再压一遍不但压不出多少体积反而要白白消耗 CPU。云服务器的 CPU 积分是有限的带宽还没打满CPU 先跑满了同步速度反而更慢。我实测过一次往一台 2 核 4G 的云服务器同步一个约 10GB 的图片目录开-z的时候 CPU 直接顶着 100%传输速度只有不开-z时的 60% 左右。后来我把压缩关掉速度立马上来了。这里的关键原则是压缩是要用 CPU 换带宽的只有带宽比 CPU 更稀缺时才值得开。如果你的目录是混合型的既有很多文本文件又有不少媒体文件更聪明的方式是用--skip-compress参数让 rsync 跳过已压缩格式rsync -avz --skip-compressjpg|jpeg|png|gif|mp4|mkv|zip|gz|bz2|xz ./webapp/ usercloud:/var/www/html/这个参数的完整默认值是7z|ace|avi|bmp|bz2|deb|gif|gz|iso|jpeg|jpg|m1v|m2v|m3u|m4a|m4b|m4p|m4v|mov|mp2|mp3|mp4|mpeg|mpg|msi|ogg|ogm|ogv|oga|pdf|png|qt|rm|rmvb|rpm|rzip|tif|tiff|tar|tbz|tgz|txz|xz|zip但不同 rsync 版本默认值略有差异显式声明更稳妥。提示判断要不要开-z有个土办法——先看源目录里文件的扩展名分布。文本类文件占比高开媒体和压缩文件占比高关。混合目录用--skip-compress兜底。2.2 限速参数 --bwlimit别让同步吃掉生产带宽--bwlimit可能是云服务器场景下最容易被人忽略但最应该被用上的参数。它的单位是 KB/s很多人第一次看文档容易当成 Mb/s 来配然后发现限速完全不符合预期。举个例子。你的云服务器带宽是 10Mbps注意小写 b理论最大下载速度是 10/8 1.25MB/s。如果 rsync 全速同步这台机器上的网站和数据库请求都会跟着卡顿。合理的做法是给 rsync 限速到带宽的 40%~60%# 10Mbps带宽取50%约等于 625 KB/s rsync -avz --bwlimit600 ./webapp/ usercloud:/var/www/html/计算过程很简单限速值(KB/s) 带宽(Mbps) × 1024 / 8 × 占用比例。10Mbps × 1024 / 8 × 0.5 ≈ 640取整到 600~640 都可以。我习惯留出一点余量防止限速值卡在带宽上限反而导致 TCP 抖动。还要注意--bwlimit只是限制单个 rsync 进程的平均传输速率如果同时跑多个 rsync 任务总带宽是叠加的。生产环境里如果要同时同步多个目录建议用--bwlimit的变体--bwlimit600,10逗号后面的数字表示“突发速率”。意思是平均限速 600KB/s但允许短期内冲到 10 倍速这能明显改善大量小文件的同步体验因为小文件传输本身对带宽的占用是不连续的。另外如果限速是为了避免影响线上业务建议配合nice命令降低 rsync 进程的 CPU 优先级nice -n 19 rsync -avz --bwlimit600 ./webapp/ usercloud:/var/www/html/2.3 断点续传与文件校验--partial、--inplace、-c 的使用边界云服务器公网传输经常遇到连接中断。默认情况下rsync 会在传输结束后删除目标端未完成的临时文件这意味着重新同步时又要从头传一遍。这对于几百 MB 的小文件还好遇到几十 GB 的大文件断一次线心态就崩了。所以云上同步我几乎必加--partial它告诉 rsync 保留不完整的文件。搭配--append-verify使用时重跑命令会从上次断掉的位置继续写完成后还会对整文件做一次校验。这个组合比--append更安全因为--append会假定已有数据是正确的不做校验。大文件同步还建议考虑--inplace。默认 rsync 会先在目标目录生成一个.文件名.xxxxxx的临时文件等全部传完后原子替换。如果目标磁盘剩余空间比较紧张临时文件和正式文件同时存在很容易把磁盘写满。--inplace直接在正式文件上写省掉这份额外空间代价是传输过程中如果出错你拿到的可能是个坏文件。我通常只在磁盘空间确实吃紧时用并且一定会搭配--append-verify保证断点续传的安全。-c参数--checksum则是永远校验文件内容而不是文件大小和 mtime。它适合数据可靠性要求极高的场景但代价很大rsync 要先读取两端全量文件计算校验和这对大目录而言几乎是全量读取的开销传输阶段反而变成次要成本。我在同步数据库备份、磁盘镜像这类“错一个字节就完蛋”的文件时才启用。下面的表格是我常用的参数组合与推荐场景参数组合适用场景核心注意点-avz文本代码类目录带宽较小压缩开销与收益要评估-av --bwlimitxxx生产云服务器同步限速值按带宽计算留余量-av --partial --append-verify大文件公网传输断线后续传不必从头再来-avW首次全量同步跳过块校验直接整个文件覆盖-avzc关键数据可靠性优先两端全量校验速度最慢3. 云服务器网络层面的优化策略TCP 与 SSH 双层调优rsync 本身的参数只是第一层。真正让云服务器同步速度产生数量级变化的往往是对底层的网络通道做优化。这一块很多人没意识到但它带来的收益比调十个 rsync 参数都大。3.1 理解带宽时延积为什么大带宽不等于高吞吐先说一个反直觉的事实你在云服务器上买 100Mbps 带宽但 rsync 传输速度可能只有 5Mbps。这种情况十有八九是 TCP 窗口太小限制住了吞吐量。TCP 协议为了保证可靠传输发送方在收到确认之前最多只能发送“一个窗口大小”的数据。这个窗口的大小上限由接收缓冲区决定。带宽时延积BDP, Bandwidth-Delay Product就是描述“在途数据量”的指标计算公式是BDP 带宽(bit/s) × 往返时延(s)假设你的服务器带宽是 100Mbps到目标云服务器的 RTT 是 50ms那么BDP 100 × 10^6 × 0.05 5,000,000 bit ≈ 625 KB也就是说TCP 接收窗口至少要 625KB才能让 100Mbps 的带宽跑满。但很多 Linux 系统的默认 TCP 读缓冲上限远低于这个值导致带宽再高吞吐也被限制在窗口能容纳的范围内。打个比方就像一段高速路限速 120但收费站每次只肯放行一辆车过闸等它跑完全程回来才放下一辆实际通行效率自然惨不忍睹。这时候需要调整云服务器端的 sysctl 参数。在/etc/sysctl.conf里追加net.core.rmem_max 16777216 net.core.wmem_max 16777216 net.ipv4.tcp_rmem 4096 87380 16777216 net.ipv4.tcp_wmem 4096 65536 16777216 net.ipv4.tcp_window_scaling 1然后执行sysctl -p生效。这里的关键是tcp_rmem的第三个值最大值和rmem_max要一起调大。注意tcp_window_scaling通常默认就是开启的但确认一下没坏处。我在一台 100Mbps 的云服务器上调完这组参数后从本地拉取数据的吞吐从 6MB/s 提升到了接近 11MB/s效果非常直观。需要提醒的是这几个 sysctl 参数是全局生效的调大缓冲区会让单条 TCP 连接占用更多系统内存但 16MB 的上限对云服务器来说完全在可控范围内。3.2 SSH 通道复用解决频繁握手的高昂开销rsync 走 ssh 模式时每执行一次命令就要建立一次完整的 TCP SSH 加密握手。公网环境下一次握手可能要 100~300ms如果业务场景是频繁、小批量的同步比如每 5 分钟同步一次增量日志握手开销在网络延迟中的占比会高得吓人。解决思路是让多个 ssh 会话复用一个连接。Linux 下可以使用 SSH 的ControlMaster特性在~/.ssh/config里配置Host * ControlMaster auto ControlPath ~/.ssh/controlmux/%r%h:%p ControlPersist 600ControlPersist 600表示主连接在最后一次会话结束后保持 600 秒期间新的 ssh/rsync 命令直接复用这条连接不再重新握手。我实际测过在 RTT 80ms 的链路上同步一个包含上千个小文件的目录开启连接复用后总耗时从 5 分 40 秒降到了 2 分 10 秒。原因是小文件单传的耗时很大一部分是固定的协议握手和数据往返延迟叠加复用连接后这部分开销直接消失了。执行前记得先创建 ControlPath 目录mkdir -p ~/.ssh/controlmux3.3 大文件与小文件的分治法带宽利用率的两个极端rsync 在处理“大量小文件”和“少量大文件”时的优化思路是截然不同的。小文件多的场景比如 node_modules、图片 CDN 静态资源目录rsync 要为每个文件建立独立的数据传输循环每个循环都有额外的往返确认开销。文件越小网络往返开销占比越大。这类场景我一般建议先把文件在本地打包再传输、解压tar -czf - ./webapp | ssh usercloud tar -xzf - -C /var/www/html/用管道把所有文件流式打包比逐文件 rsync 更省连接开销吞吐量能翻几倍。当然这样每次都是全量传输没有增量优势。如果你既要增量又要处理海量小文件可以配合--files-from参数先用 find 生成文件列表再让 rsync 按列表同步find ./webapp -type f -newer ./webapp/.last_sync | sed s|^\./|| /tmp/filelist.txt rsync -av --files-from/tmp/filelist.txt ./webapp/ usercloud:/var/www/html/大文件场景则相反。rsync 默认的增量算法会把文件分成小块并计算校验和这是为了减少增量传输的数据量但首次全量传输时这些校验计算纯属徒劳。此时应该用-W--whole-file参数直接把整个文件推过去不做块校验。首次全量同步几百 GB 的文件时-W能节省掉大量的两端 CPU 计算时间。还有一个经常被忽略的选项是 rsync daemon 模式。如果两台云服务器都在同一个云厂商的内网里走内网 IP 用 daemon 模式同步速度会比走 ssh 快很多因为 daemon 模式少了 SSH 的加密开销而且可以直接利用内网带宽。这一点在第 4 章实践里会详细展开。4. 实操复盘三种典型云服务器同步场景的完整配置前面讲了很多原理和参数这一章我把实际遇到过且验证过的三个典型场景完整还原出来包括当时的选型思考、碰到的问题和最终落地命令你可以直接参考或改造。4.1 本地到云服务器的首次全量 日常增量同步场景是我接管的一台个人网站云服务器本地站点目录约 50GB包含大量图片、JS/CSS 资源和 PHP 代码服务器的公网带宽是 8Mbps。我的目标是先把本地存量数据推送到云上之后每天凌晨做一次增量同步。首次全量我用的命令是rsync -avW --partial --bwlimit450 -e ssh ./webapp/ user123.45.67.89:/var/www/html/选-W是因为存量文件中大部分都是图片两边文件没有共同的块做块校验没有意义选--bwlimit450是因为 8Mbps 带宽换算后约 1024KB/s为了让用户访问网站不卡我留出一多半带宽给线上流量限速到 45% 左右。实测全量传输大约用了 7 个多小时期间网站访问没有明显波动。日常增量我用的是rsync -avz --delete --partial --bwlimit450 --skip-compressjpg|jpeg|png|gif|zip|gz ./webapp/ user123.45.67.89:/var/www/html/这里加回-z是因为增量内容以代码和文本日志为主压缩收益高--delete保持两端目录严格一致删除源端已移除的文件。为了让日常同步不出意外我用--dry-run先演练一遍是雷打不动的习惯rsync -avz --delete --dry-run ./webapp/ user123.45.67.89:/var/www/html/--dry-run只列出将要执行的操作不真正传输。我看到列出的文件列表和大小都在预期范围内再跑正式命令。这一步看似多余实则能避免很多因为路径写错导致的灾难性覆盖。4.2 云服务器之间数据迁移rsync daemon 模式实战有一次需要把一台华东区云服务器上的全部数据迁移到同厂商的华南区新机器上。两台机器在同一个云厂商的内网里走内网传输比走公网快得多所以我启用了 rsync daemon 模式。在源服务器上编辑/etc/rsyncd.confuid root gid root use chroot yes max connections 4 syslog facility local5 pid file /var/run/rsyncd.pid lock file /var/run/rsync.lock [data] path /data comment data migration read only yes list no auth users syncuser secrets file /etc/rsyncd.secrets然后在/etc/rsyncd.secrets里写入syncuser:你的强密码密码文件权限一定要设为 600否则 rsync daemon 会拒绝启动chmod 600 /etc/rsyncd.secrets systemctl start rsyncd目标服务器上执行拉取rsync -avP --bwlimit80000 --password-file/etc/rsync_pass syncuser源服务器内网IP::data /data/--password-file指定一个只包含密码的文件这样命令不会出现在 shell 历史里。内网带宽足够的情况下我把限速提到了 80MB/s 量级只做了一层保险。整个迁移 1.2TB 的数据耗时约 4 小时并且中途断过一次配合--partial重跑后自动续传没有浪费前面的进度。注意rsync daemon 模式默认没有加密走公网时数据是明文传输。如果两台机器不在同一内网还是建议用rsync -av -e ssh userhost::module的写法让 ssh 先建一条加密隧道再访问 daemon。4.3 定时增量备份 日志落盘的完整脚本最后分享一个我日常在用的备份脚本作用和网易云音乐里的“每日推荐”一样——到点自动干活干完自动汇报不用人管。脚本逻辑分三块用flock加锁防止上一次同步还没跑完下一次又启动用--bwlimit限速避免影响白天业务每次同步后把结果写入结构化日志方便事后排查。#!/bin/bash # 云服务器增量备份脚本 # 用法./backup_to_cloud.sh LOCK_FILE/tmp/rsync_backup.lock LOG_FILE/var/log/rsync_backup.log SOURCE_DIR/var/www/html DESTuser你的云服务器IP:/home/backup/$(date %Y%m%d) BW_LIMIT500 exec 9$LOCK_FILE if ! flock -n 9; then echo $(date %Y-%m-%d %H:%M:%S) [ERROR] Another instance is running, exit. $LOG_FILE exit 1 fi echo $(date %Y-%m-%d %H:%M:%S) [INFO] Backup started. $LOG_FILE rsync -avz --delete --partial \ --bwlimit$BW_LIMIT \ --log-file$LOG_FILE \ --excludecache/ \ --excludetmp/ \ $SOURCE_DIR/ $DEST/ $LOG_FILE 21 if [ $? -eq 0 ]; then echo $(date %Y-%m-%d %H:%M:%S) [INFO] Backup completed. $LOG_FILE else echo $(date %Y-%m-%d %H:%M:%S) [ERROR] Backup failed, please check. $LOG_FILE fi # 清理 7 天前的备份 find /home/backup -maxdepth 1 -type d -mtime 7 -exec rm -rf {} \;注意脚本里我把每天的备份放到了独立日期目录下这样能保留历史版本。如果你只想保留最新一份镜像把DEST改成固定路径去掉日期变量即可。另外--log-file参数可以让 rsync 自己输出每个文件传输的详细日志排错时比只记录命令退出码有用得多。配合 crontab 就可以做到无人值守0 2 * * * /root/backup_to_cloud.sh5. 常见问题与排查技巧实录5.1 同步速度上不去的三个排查方向很多人在云服务器上遇到“rsync 半天传不完”的情况第一反应是加带宽但往往加了带宽问题依旧。根据我的经验速度上不去要从三个方向排查它们是叠加关系不是单选题。第一步看 CPU。执行top -u rsync或者ps aux | grep rsync看进程的 CPU 占用。如果 CPU 已经接近 100%说明瓶颈在压缩或校验计算上。先试试去掉-z或者把--skip-compress的扩展名列表加全大部分问题都能缓解。第二步看网络链路。用iperf3测一下裸 TCP 的最大吞吐# 云服务器端服务端 iperf3 -s # 本地端客户端 iperf3 -c 云服务器IP -R -t 30 -P 4如果 iperf3 测出来的吞吐远低于带宽预期说明是链路本身或 TCP 参数的问题。这里重点看两个数据retr重传次数和 jitter。重传率高说明网络丢包严重优先考虑是不是跨运营商、高峰期链路拥堵RTT 高但重传率低则大概率是 TCP 窗口太小回到第 3 章调 sysctl 参数。第三步看磁盘 IO。iostat -x 1查看%util如果磁盘写等待非常高网络带宽根本没法打满这台机器的磁盘吞吐本身就成了瓶颈。云服务器常见的是 IOPS 限制大量小文件同步时尤其明显。解决方案是分治——先把小文件打包成大文件再传输全量同步后用增量维护。这三个方向可以整理成一张速查表现象可能原因优先排查手段CPU 100%传输慢压缩参数选择不当去掉-z或配置--skip-compress带宽打不满重传多链路丢包或拥塞控制差iperf3 测链路检查 RTT 和重传率延迟高但重传少TCP 窗口过小调大rmem/wmemsysctl 参数网络正常但速度波动大磁盘 IO 瓶颈iostat -x 1看%util5.2 传输中断、校验失败怎么处理公网传输中断是很常见的事不用慌。我的处理流程是先确认源端和目标端的 rsync 版本差异版本差异会导致某些参数行为不一致比如老版本不支持--append-verify然后在重跑时加上--partial --append-verify让同步从断点继续而不是重头开始。如果同步完成后发现两端文件校验不一致大概率是传输过程中出了问题或者目标端磁盘有静默写坏。这时先用rsync -avc --dry-run做一次全量校验找出所有不一致的文件再单独重传这些文件。需要说明的是-c是逐字节校验非常耗时间不适合作为常规同步参数只适合这种“出了事要彻查”的场合。还有一类中断是 ssh 连接被杀导致的。云服务商的安全策略会主动中断长时间空闲或超过一定时长的连接此时可以在 ssh 命令里加上-o ServerAliveInterval30选项每 30 秒发一个 keepalive 包保持连接活跃rsync -avz -e ssh -o ServerAliveInterval30 -o ServerAliveCountMax3 ./webapp/ usercloud:/var/www/html/5.3 容易踩的坑软链接、权限和时间戳最后记录几个我在实际同步中经常踩、且文档里容易忽略的细节。软链接处理是头号坑。-a参数默认会保留软链接本身-l不会跟随链接复制目标文件。这通常是期望行为但如果你用-L--copy-linksrsync 会跟随软链接复制真实文件一个软链接指向超大目录时可能把你自己都想不到的海量数据传到目标端。我的建议是除非明确知道自己在干什么否则不要用-L。已经同步过的目录想检查有没有软链接“越界”用这条命令find /var/www/html -type l -ls权限和时间戳是另一个高频问题。跨服务器同步时两端用户 UID/GID 不一致会导致属主错乱。比如源端文件属主是 UID 1000目标端 UID 1000 恰好是另一个用户同步过去后权限就错了。此时可以用--usermap和--groupmap做显式映射rsync -av --usermap1000:www-data --groupmap1000:www-data ./webapp/ usercloud:/var/www/html/还有时区问题。rsync 默认通过 mtime 判断文件是否变更如果目标服务器和源服务器的时区或系统时间不一致可能会造成大量文件反复被判定为“已修改”。同步前先对比两端时间date两端误差大时用 NTP 同步一下再跑 rsync。这个问题最容易在云服务器迁移时被忽略一共两条命令的事但踩进去的人不少。根据我自己的经验rsync 同步优化其实没有太多玄学先理解网络链路的瓶颈再按数据特征选参数最后用增量、限速、断点续传这套组合兜底基本上就能把云服务器同步这件事做得又快又稳。最后再分享一个小技巧任何一次大规模同步之前先用--dry-run配合--stats看一眼预览结果能帮你提前发现路径写错、要传的文件比预期多这些隐藏问题五分钟的预览能省掉后面一整天的回滚功夫。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价