Rsync性能优化实战:从30MB/s到200MB/s+的调优全记录

发布时间:2026/9/16 3:12:16
Rsync性能优化实战:从30MB/s到200MB/s+的调优全记录 Rsync 这个工具我想搞服务器运维和开发的人都不陌生尤其是数据备份、日志同步、文件分发这些场景基本就是首选方案。但问题来了很多人在使用 rsync 的时候都会遇到一个尴尬的情况小文件同步倒是没什么感觉一旦数据量大一点、文件数量多一点传输速度就直线下降有的甚至比 scp 还慢严重的时候几百 GB 的数据要同步好几天完全没法接受。这篇文章我想把 rsync 性能优化的整个思路讲透。我从实际项目里踩过的坑出发带着你一步步定位慢在哪、为什么慢、怎么调核心内容包括瓶颈定位方法、关键参数的解释与选择、海量小文件的处理策略、以及我从 30MB/s 干到 200MB/s 的完整调优记录。适合正在处理大规模数据同步的运维工程师、备份方案的开发者以及所有被 rsync 速度折磨过的朋友。1. 先搞清楚Rsync 为什么慢瓶颈到底在哪1.1 从一次真实“慢同步”说起我记得很清楚有个项目要把生产环境的一批数据文件从一台服务器同步到另一台总共大概 2.8TB文件数量超过 300 万。初始命令非常简单rsync -av /data/ userbackup-server:/backup/跑了 6 个小时同步进度还不到 10%。当时第一反应就是网络不行但拿 iperf3 一测千兆网卡完全跑满网络本身没有任何问题。这就引出一个很核心的问题rsync 慢瓶颈往往不在网络上。我们用 top 看了一下rsync 进程的 CPU 占用率直接飙到 150% 以上而且大量时间花在了用户态。磁盘 iotop 显示读写的等待时间也比较高。这其实已经说明了问题——rsync 的增量算法也就是滚动校验和计算是非常吃 CPU 的。文件数量越多、被切分的块数越多CPU 开销就越明显。尤其当数据里有海量小文件时每个文件都要走一遍“打开、读取、分块、算校验、比对、传输”的流程这中间的开销分摊到每个文件上就成了巨大的性能杀手。1.2 三步定位 Rsync 性能瓶颈我后面总结了一套判断方法核心思路是“分层排查、逐项排除”。无论你的场景是什么样的都可以按这三步走第一步先确认网络是不是瓶颈。用 iperf3 打满两端带宽或者直接看 rsync --progress 输出的传输速度再对比两端网卡的最大速率。如果 iperf 能跑到 900 Mb/s而 rsync 只能跑几十 MB/s那问题大概率不在网络。第二步确认磁盘够不够快。最简单的方法是在源服务器本地做一次 rsync 测试目标路径也用本机比如time rsync -av /data/ /tmp/test/这样完全绕开网络如果本地同步都只有几十 MB/s那就说明磁盘 I/O 或 CPU 算法是主要瓶颈。这一步很关键很多人习惯性把锅甩给网络其实本地就跑不快。第三步区分大文件还是小文件。用 find 统计文件数量和大小的分布情况比如find /data -type f | wc -l find /data -type f -size 100M | wc -l如果大文件很多但速度依然上不去那重点查 CPU 和磁盘如果小文件极多那问题更复杂我后面专门用一章讲小文件的处理策略。1.3 别急着加参数先看清传输链路这里我还要多说一句很多教程上来就让你加一堆参数比如 -z --partial --inplace看起来高大上实际没搞清自己的场景反而更慢。比如 -z 压缩参数在千兆内网下多数时候是负优化因为 CPU 的压缩开销远大于网络上省下的那点流量。所以在动手调优之前务必先回答这几个问题源和目标之间是局域网还是公网带宽多少数据以什么形态为主大文件多还是小文件多两端机器 CPU 性能如何同步频率是多久一次全量多还是增量多把这几个问题想清楚了再去挑选和组合参数才不会瞎调。rsync 的性能调优本质上不是“参数越多越好”而是“参数与场景匹配”。2. 核心参数深度调优哪些参数真正影响速度2.1 -z 压缩的真相低带宽救命高带宽拖后腿-z 参数是 rsync 最常用的优化手段之一但也是最容易被误用的。它会在传输前对数据进行压缩目标端再解压目的是减少网络传输的数据量。在公网、跨机房、低带宽的场景下-z 往往能带来几倍的速度提升比如原本要传 5GB 的数据压缩后可能只有 1.5GB虽然 CPU 有开销但总体时间反而大幅缩短。但换成千兆以上的内网环境情况完全反过来。千兆内网的传输瓶颈从带宽转移到了 CPU 和磁盘-z 的压缩计算会白白吃掉大量 CPU 资源。我实测过一个 10GB 的文件在千兆内网不加 -z 传输耗时 60 多秒加上 -z 反而飙到 120 秒开外速度直接腰斩。所以我的建议是跨公网、带宽小于 100Mb/s 的场景可以开 -z千兆内网场景除非文件内容重复度极高比如纯文本日志否则不建议开。如果确实要开用 --compress-level 控制压缩级别别默认跑最高级rsync -az --compress-level6 --partial /data/ userremote:/backup/还有一种更精细的做法--skip-compress 参数可以跳过已经压缩过的文件扩展名如 zip、gz、mp4、jpg 等避免对这些文件做无意义的压缩计算。这个参数我在日志同步和媒体文件备份时经常用效果立竿见影。2.2 --inplace 与临时文件策略的选择rsync 默认的传输方式是先写到目标目录的隐藏临时文件等文件传完再 rename 成正式文件。这样做的好处是传输过程中目标文件始终是完整的不会因为中断而损坏但代价是多了一次写入和一次重命名操作在大量文件同步时会产生明显的 I/O 开销。--inplace 参数会直接覆盖目标文件不经过临时文件再 rename。这个参数有两个很直观的好处一是少了一次 mv 操作小文件的同步速度会提升二是对某些磁盘空间极少的场景比较友好不用在磁盘上额外留出跟文件等大的临时空间。但这块有个大坑--inplace 在增量同步时如果传输中途断掉目标文件就已经是损坏状态了没有“备份”可回退。另外它对某些数据库文件的在线热备场景也需要注意因为直接原地覆盖可能会导致数据库读到一个写了一半的文件。所以我通常只在磁盘空间紧张、且同步失败可接受重跑的场景下才用 --inplace生产环境的备份任务我还是优先保留临时文件机制。这里再补充一个参数--partial。它允许保留传输失败时已下载的部分文件而不是直接删除。配合 --append 或 --append-verify 可以断点续传。注意 --partial 和 --temp-dir 搭配效果好。rsync 默认会在传输结束后删除临时文件如果网络不稳定--partial 能让你下次同步省去已经传过的部分实测在 100Mb/s 公网大文件同步场景下非常有用。2.3 增量 vs 整文件什么时候该用 -Wrsync 引以为傲的是增量同步它会把文件切成一个个块先比对块差异然后只传变化的部分和新增内容。这个机制对小修改、大文件做增量备份是神器比如一个 10GB 的日志文件只追加了几百 MB增量同步只要传新增那部分速度极快。但增量同步也有代价它需要对文件做分块和校验和计算如果目标端根本不存在对应文件或者两端文件内容基本完全不同那这些计算就全成了浪费。这种情况下可以用 -W--whole-file参数让 rsync 不做分块差异比对直接把整个文件传过去。这在本地或者高速局域网同步大文件、新文件时非常高效。我的实践经验是首次全量同步、大规模文件迁移时直接用 -W比默认增量模式快不少。等数据基线稳定之后再用默认的增量模式跑日常变化。这里给个小命令行参考rsync -avW --partial /data/ userremote:/backup/不过 -W 在增量场景下反而可能会更慢因为失去了“只传差异”的优势。所以记住一句话新文件多的时候用 -W旧文件多且改动小的时候用默认增量。2.4 TCP 缓冲区与 socket 参数在网络大文件传输场景中TCP 的默认缓冲区大小往往不够。尤其是有一定延迟的长肥网络高带宽时延积默认缓冲区会导致实际吞吐率上不去。rsync 的 --sockopts 参数允许你调整 TCP 缓冲区尺寸比如rsync -av --sockoptsSO_RCVBUF8388608,SO_SNDBUF8388608 /data/ userremote:/backup/单位是字节这里设置的是 8MB。8MB 这个值是我在千兆内网和百兆公网环境反复测试后的一个折中值既不会吃掉太多内存又能有效提升大文件传输的吞吐率。如果你的内存非常充裕、网络延迟又比较大可以试着调高一些到 16MB但要配合操作系统级别的 tcp_rmem/tcp_wmem 配置否则可能被内核默认上限卡住。还要提一个关键点rsync 的协议版本。目前 rsync 3.x 的默认协议是 30如果你的目标是老机器可能还停留在 2.x 的协议那有些性能优化参数是用不了的。两端尽量升级到 rsync 3.1.0 以上遇到跨版本问题可以先在两端分别执行 rsync --version 确认。3. 大数据量与海量小文件场景的传输优化3.1 海量小文件为什么慢这个问题我单独拎出来讲因为它是很多运维同学“rsync 好慢”的第一大元凶。上面提到过rsync 的增量同步需要对每个文件做校验和计算而小文件的文件头、块头、元数据开销在总数据量中占比极高。更关键的是每个文件传输都要经过“打开文件、读取、计算校验、发送、确认”这么一条链路小文件越多这种握手和往返的占比就越高。举个例子如果你有 100 万个 1KB 的小文件总数据量才 1GB 左右看起来很小但 rsync 传输时可能要花几个小时。这跟只传一个 1GB 大文件是完全不同的量级因为瓶颈全部落在了 CPU 和文件系统 I/O 上。我实测过一个包含 80 万个小文件的目录rsync 全量同步大概跑了 50 分钟才完成而把它打成一个 tar 包后传输同样数据不到 3 分钟。3.2 打包传输的对象选择那是不是所有小文件场景都一刀切打包也不是。打包传输的前提是两端能接受“用一个或几个压缩包代替原本的目录结构”这种传递方式。如果目标端希望保持目录结构随时可读那打包完之后还得在目标端解包这中间的磁盘占用和耗时也要考虑进去。我常用的方案是源端先 tar不做压缩或者只做轻量压缩然后 rsync 把 tar 包传过去目标端再解包。命令大致是tar -cf data.tar -C /data . rsync -av --partial data.tar userremote:/backup/ ssh userremote mkdir -p /backup/data tar -xf /backup/data.tar -C /backup/data这里为什么不建议 tar 的时候直接加 -z因为 tar 加 -z 会把 CPU 压缩和磁盘都压在源端在多核机器上其实可以并行但在单核低配服务器上会非常慢。而且很多数据本身是日志、压缩包文件tar 的压缩率并不理想反而耽误时间。我的经验是如果数据里文本和日志比例高可以 tar 后单独再用 zstd 或 pigz 这类并行压缩工具压一遍如果多媒体和压缩包占比高那就别压缩直接裸 tar 传。3.3 --files-from 分批同步技巧有时候你不能打包因为目标端要求目录结构实时可用或者数据量太大没有额外磁盘空间放打包文件。这时可以试试按批次同步用 --files-from 参数把要同步的文件列表写到一个文件里让 rsync 只处理这些文件。find /data -type f -mtime -1 /tmp/files_to_sync.txt rsync -av --files-from/tmp/files_to_sync.txt / /backup/注意 --files-from 里的路径是相对于源路径的所以源路径要写对。这种分批同步策略特别适合“每天增量同步一部分、错峰执行”的场景比如白天同步当天修改的文件夜里再同步历史的大文件避免一次全量同步把所有 I/O 打满影响线上业务。另外--files-from 还有一个妙用排除掉巨大的、根本不需要同步的目录。比如数据目录里有一些视频缓存超过 10GB你完全不想同步但又碍于目录结构不能简单排除这时就可以通过筛选文件列表来控制。3.4 并行 rsync 与带宽控制单个 rsync 进程跑不满带宽时很多人会想到并行多个 rsync。这个思路是对的但要注意不是越多越好。并行数取决于源端磁盘的随机读能力、目标端磁盘的写入能力以及文件数量。如果并行太多磁盘 I/O 反而会变成瓶颈甚至导致文件系统拥塞。我常用的做法是先按顶层目录把数据拆成几份然后分别用 rsync 同步例如for dir in /data/project1 /data/project2 /data/project3; do rsync -av $dir userremote:/backup/ done wait这里用 和 wait让多个 rsync 同时在后台跑。在双核 CPU 普通 SATA 磁盘的环境下我实测并行 3 个就能把千兆内网跑满再往上加效果不明显反而会因为频繁的磁盘排队导致每个 rsync 都在等待磁盘整体速率不升反降。如果想要更严格地限制速度避免同步任务把业务流量挤没可以用 --bwlimit。例如 --bwlimit10000 表示限速 10MB/s单位是 KB/s。带宽限制通常在公网传输和混合业务场景下很有用。4. 实操记录从“慢同步”到“高效传输”的完整调优过程4.1 场景设定与初始状态这里分享一个我印象很深的真实案例。当时要同步的目录 /data 大概 2.8TB文件数 300 多万其中小文件极多很多是几 KB 的配置和缓存文件还有一些几百 MB 到几 GB 的媒体包。源服务器和目标服务器都在同一机房千兆内网CPU 是双路 E5磁盘是 RAID10。初始命令是很常规的rsync -av /data/ backup172.16.10.5:/backup/跑起来发现同步速度在 30MB/s 左右徘徊预计要 24 小时以上。这个速度在千兆内网里是明显不达标的千兆的理论上限是 125MB/s实际能稳定跑 100MB/s 左右才算正常。4.2 第一步去掉 -z调整压缩策略我们检查了命令发现系统里有一些默认脚本把 -z 加上了。因为同机房千兆内网带宽极大-z 带来的 CPU 开销开始拖后腿。我们先把 -z 去掉改成 --compress-level3 只对文本类数据做轻量压缩同时给 rsync 的进程省了很多 CPU。结果速度从 30MB/s 提升到了 50MB/s 左右提升明显但还是不够理想。这时候我意识到小文件占比过高是主要问题300 多万个文件光是文件遍历和校验的计算就很重。4.3 第二步并行 rsync 分批排除我们采取了两步操作。第一步先把目录里的大文件100MB单独筛出来用 -W 做整文件传输避免增量校验的额外开销第二步对小文件目录按项目子目录拆分成多个批次用 --files-from 分批同步。这种组合的效果非常好。大文件部分用find /data -type f -size 100M /tmp/bigfiles.txt rsync -avW --delete --files-from/tmp/bigfiles.txt / backup172.16.10.5:/backup/小文件部分拆成 4 个并行进程每个按子目录同步。最终整体的同步速度稳定在 200MB/s 以上远超出了千兆内网单流的上限这其实是并行多流带来的效果。注意单条 rsync 链路的吞吐率依然被千兆带宽限制但并行之后的总吞吐率会显著提高。4.4 第三步持续增量与断点恢复全量同步完成后我们把日常增量备份脚本改成如下形态rsync -az --partial --append-verify --delete \ --exclude *.tmp --exclude cache/* \ /data/ backup172.16.10.5:/backup/这里的 --append-verify 只用于那些日志类、追加写入型的文件能极大减少每次扫描的开销。整体从最初估算的 24 小时压到全量 3.5 小时完成日常增量 5 分钟之内跑完。而且因为加上了 --partial 和断点续传参数中间偶尔网络抖动也不怕了重跑一次会自动跳过已传过的数据。4.5 调优后的效果对比为了让你有一个直观感受我把优化前后整理成一张表指标优化前优化后初始速度30MB/s平均 200MB/s预计全量时间24-36h3.5hCPU占用高校验压缩中按需压缩传输中断处理基本重来断点续传小文件处理全部默认校验分批并行文件列表控制这张表不是说每个场景都能达到同样效果但它很能说明一件事rsync 慢很多时候不是工具本身的缺陷而是参数选择、数据特征和传输策略不匹配。把这三者对齐性能提升一个数量级是完全可能的。5. 常见问题与性能排查技巧实录5.1 典型问题速查表我把这些年遇到的高频 rsync 性能问题整理成速查表方便你对照处理现象常见原因推荐解法传输速度上不去且CPU高开启了 -z 压缩小文件过多去掉 -z或 --compress-level 降级大文件用 -W速度上不去但CPU不高磁盘I/O瓶颈或TCP缓冲区太小检查 iotop/pidstat用 --sockopts 调大缓冲区大量小文件同步极慢每个文件都有握手和校验开销打包传输或 --files-from 分批并行 rsync网络中断后需要重传没有开启 --partial加 --partial大文件可配合 --append目标端磁盘空间不足临时文件机制占用双倍空间用 --inplace但要注意损坏风险同步了几天还没有完成没有做分批或并行拆分子目录后台 并行备份对象包含大量压缩包-z 反而浪费CPU用 --skip-compress 跳过已压缩扩展名5.2 中断恢复与数据一致性排查同步中断是运维日常rsync 主要通过 --partial 和 --append 来优化恢复体验。但很多人在第一次断线后没意识到恢复时 rsync 默认还会重新比对已传文件块所以如果文件特别大恢复也会花一些时间。这时候可以用 --append 跳过比对直接追加剩余部分适用于日志这种只追加的文件。如果担心追加的数据不完整再用 --append-verify它会在追加前做一次校验。在使用 --delete 参数时也有一个常见风险如果不小心把源路径写错rsync 可能会把目标端该目录下的文件删掉。所以大项目第一次使用 --delete 之前建议先在命令里加 --dry-run-n看一遍输出确认哪些文件会被删除养成这个习惯能救你很多次。5.3 监控进度与实时性能rsync 自带的 --progress 可以显示每个文件的传输进度和速率但文件特别多时刷屏很严重而且统计维度比较粗糙。想要更精确的监控我会建议用 --infoprogress2 只显示总的传输进度不逐个文件刷屏rsync -a --infoprogress2 /data/ userremote:/backup/用 iotop 盯着源端磁盘读确认瓶颈到底在磁盘还是在网络用 iftop 盯着目标端网络流量确认带宽有没有被合理压满用 dstat 综合看 CPU、磁盘、网络三项指标排查时能省不少时间。这套组合命令我几乎每个 rsync 调优项目都会跑一轮先用 dstat 确认瓶颈再针对性加固调优效率会高出很多。5.4 经验技巧补充最后补充一些零散但我个人觉得很有用的点。第一rsync 的 --exclude 和 --include 组合可以做得非常细比如排除缓存目录但保留几个需要同步的缓存子目录。这类规则要集中写到一个排除文件里用 --exclude-from 读取方便统一维护。第二遇到“目标端文件被占用导致同步报错”的情况先搞清楚占用进程再决定是否断开不要盲目用参数强制覆盖。比如你在同步某个应用的数据目录目标端应用还在写这些文件--delete 又恰好开启很容易出现一边删一边写的混乱状态。第三跨平台场景源端是 Windows 时用 cwRsync 能解决但参数选择和文件路径处理都要小心。Windows 下路径分隔符、权限属性、隐藏文件这些跟 Linux 的表现都不完全一样建议先用 --dry-run 验证。第四即使 rsync 参数调优已经很到位也不要忽略“数据特征”这个前提。比如你同步的是数据库文件很多数据库像 MySQL 的 InnoDB有自己的一致性视图机制直接用 rsync 热备不一定安全生产环境还是要配合数据库自身的备份工具或快照来做。这算是题外话但确实影响你对“同步结果是否可用”的判断。在我这些年用 rsync 的经验里印象最深的一条不是某个参数多好用而是“先定位瓶颈、再选参数”这个习惯。很多人一上来就翻参数手册把能加的优化参数全堆上结果要么无效、要么反而更慢。rsync 的性能调优本质上是理解数据流、网络、CPU、磁盘这四个资源之间的关系再把 rsync 的工作机制对齐到你的场景里。只要这个思路对了参数选择只是顺手的事。如果你现在正被某个同步任务折磨不妨按照文章里的三步定位法先看一眼瓶颈到底在哪再动手改我相信结果一定会让你意外。