解决rsync同步文件时卡住且疯狂消耗资源的问题
本文完整阅读约需 12 分钟,如时间较长请考虑收藏后慢慢阅读~
最近,我将所租用服务器上所有的数据(接近500G)使用crontab+rsync同步到了Time4VPS的存储服务器,以防硬件故障造成数据丢失。
然而在同步过程中,却出现了消耗掉服务器所有资源(内存&CPU&磁盘)的问题。
首先附上我的crontab配置:
0 * * * * root echo `date` >> /home/rsync.log && rsync -avu --progress --delete --checksum --compress /home/lurenjia [email protected]:/home/backup/ >> /home/rsync.log
这个配置看起来没有任何问题,但是一旦运行,就会出现如下图所示的情况:
图中可以看到,磁盘延迟已经高达3000ms,除此之外同时还伴随着备份服务器(虚拟机)Linux内存耗尽的警告,终端不响应任何操作,CPU占用率为100%。
发现问题后,我立刻关闭虚拟机的电源,重启后删除掉crontab,开始着手排查原因。
最开始我认为问题出在crontab本身的配置,但在确认crontab之后,发现crontab并没有出现问题,上面0 * * * *
的配置即每小时0分执行命令。
我尝试执行crontab中的命令(当时写了之后忘了尝试性执行一下,实在是失策),却发现卡在了sending incremental file list
上。
使用screen退出当前session,运行top发现rsync正在疯狂地使用CPU资源,而运行iotop发现rsync正在疯狂地读取磁盘。
$ iotop
Total DISK READ : 102.55 M/s | Total DISK WRITE : 0.00 B/s
Actual DISK READ: 102.55 M/s | Actual DISK WRITE: 0.00 B/s
TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
6726 be/4 root 102.55 M/s 0.00 B/s 0.00 % 48.84 % rsync -avu --progress --delete --compress --checksum /home/lurenjia [email protected]:/home/backup/
...
问题来了:同步只需要读取文件列表与摘要,那么rsync到底在做什么操作,造成如此大的磁盘IO开销呢?
我使用man rsync
阅读rsync的文档,希望从文档中找到造成如此大磁盘IO开销的『罪魁祸首』。这时候我突然发现一段参数说明:
OPTIONS SUMMARY
Here is a short summary of the options available in rsync. Please refer to the detailed description below for a complete description.
-v, --verbose increase verbosity
--info=FLAGS fine-grained informational verbosity
--debug=FLAGS fine-grained debug verbosity
--msgs2stderr special output handling for debugging
-q, --quiet suppress non-error messages
--no-motd suppress daemon-mode MOTD (see caveat)
-c, --checksum skip based on checksum, not mod-time & size
-a, --archive archive mode; equals -rlptgoD (no -H,-A,-X)
--no-OPTION turn off an implied OPTION (e.g. --no-D)
-r, --recursive recurse into directories
-R, --relative use relative path names
注意--checksum
参数的说明:根据文件校验值进行文件比对,而非修改时间与文件体积。
就是这里!造成巨大磁盘IO的罪魁祸首就是这个参数,500G文件在本地和备份服务器端全部读取&校验需要很长的时间,而前一个任务尚未执行完毕,后一个任务又来了,如此往复,造成Linux磁盘高IO的同时,也让系统由于内存不足而崩溃。
既然找到了罪魁祸首,那么解决这一问题就非常简单:在命令中删除--checksum
参数即可。
删除该参数后,同步时间果然飞快。但这时候我想到了另一个问题:如果只校验修改时间与文件体积,是否能保证文件真正得到同步呢?
我尝试了在修改文件内容(保持大小不变)后将修改时间恢复原状的情况,结论是:在修改时间和文件体积不变的情况下,rsync会漏掉该文件,导致同步不完全。但是这种情况实在是少之又少,所以说一般我们不需要考虑漏掉文件的问题。
如果实在担心漏掉文件的话,可以使用两种方式解决:
1. 加上--checksum
参数。这种方式尽管极慢,而且对磁盘可能有损伤,但是是最万无一失的,如果存在很重要(例如数据库、日志)、但是不是很大(差不多1G以内)的文件,可以使用该方式进行同步。
2. 隔一段时间删除备份服务器上所有数据,并重新进行全量同步。该方式适合文件较大较多的情况,定期的全量同步也可以解决同步不完全的情况。