为什么rsync不进行增量传输

为什么rsync不进行增量传输

我有大约 77MB 的二进制文件:

nupic@nupic-virtualbox:~/VboxSharedFolder/experiments/sync/exp2$ ls -lah src/
total 77M
drwxrwx--- 1 root vboxsf    0 Jun 21 13:31 .
drwxrwx--- 1 root vboxsf 4.0K Jun 21 16:21 ..
-rwxrwx--- 1 root vboxsf  77M May 27  2014 binary.bin

我一直在玩rsync它的​​增量算法功能,看看它是如何工作的。想法是在二进制文件中做出微小的差异,并查看使用多种方法传输了多少数据。为了这些目的,我制作了非常简单的脚本:

#!/bin/bash
# rsync does not trnansfers delta over local by default
sed 's%\x00\x00\x00\x20\x66\x74\x79\x70\x69\x73\x6f\x6d\x00\x00\x02\x00%\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11%' src/binary.bin > dst/binary.bin
strace -f -e trace=read,write -o rw_rsync_local_default.log rsync -avcz --progress src/ dst/

# rsync -no-W should enables delta tranfer no matter if local or remote
sed 's%\x00\x00\x00\x20\x66\x74\x79\x70\x69\x73\x6f\x6d\x00\x00\x02\x00%\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11%' src/binary.bin > dst/binary.bin
strace -f -e trace=read,write -o rw_rsync_local_delta_enabled.log rsync --no-W -avcz --progress src/ dst/

# rsync trnansfers delta over network by default
sed 's%\x00\x00\x00\x20\x66\x74\x79\x70\x69\x73\x6f\x6d\x00\x00\x02\x00%\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11%' src/binary.bin > dst/binary.bin
strace -f -e trace=read,write -o rw_rsync_remote.log rsync -avcz -e "ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" --progress src/ nupic@localhost:/home/nupic/VboxSharedFolder/experiments/sync/exp2/dst/

# scp should transfers whole file not delta
sed 's%\x00\x00\x00\x20\x66\x74\x79\x70\x69\x73\x6f\x6d\x00\x00\x02\x00%\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11%' src/binary.bin > dst/binary.bin
strace -f -e trace=read,write -o rw_scp.log scp src/binary.bin nupic@localhost:/home/nupic/VboxSharedFolder/experiments/sync/exp2/dst/

# cp always transfers whole file not delta
sed 's%\x00\x00\x00\x20\x66\x74\x79\x70\x69\x73\x6f\x6d\x00\x00\x02\x00%\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11%' src/binary.bin > dst/binary.bin
strace -f -e trace=read,write -o rw_cp.log cp src/binary.bin dst/binary.bin

然后我有以下循环来评估结果:

for i in *.log; do
  echo $i; cat $i | grep write | awk 'BEGIN {FS="="}{ sum += $2} END {print sum/1024/1024 "MB"}';
  echo "###########";
done

结果如下:

rw_cp.log
67.8075MB
###########
rw_rsync_local_default.log
146.697MB
###########
rw_rsync_local_delta_enabled.log
66.8765MB
###########
rw_rsync_remote.log
0.0707941MB
###########
rw_scp.log
136.048MB
###########

从这五个实验中,我只有两个是清楚的:

  1. cp写入的字节数与原始文件的大小大致相同 ( rw_cp.log)。
  2. rsync当目的地是远程的(通过网络)时使用增量算法 ( rw_rsync_remote.log)

以下是我不清楚的事情:

  1. 为什么调用rsyncon Bothsrcdston localhostwrite 大约是原始文件大小的两倍字节? ( rw_rsync_local_default.log)
  2. 为什么--no-W选项 forrsync不按规定仅传输 delta forsrcdstonlocalhost这里为什么它仍然传输大约整个文件? ( rw_rsync_local_delta_enabled.log)
  3. 额外提示:为什么scp传输的字节数大约是原始文件大小的两倍?我知道有一些加密,但两次对我来说似乎很大(rw_scp.log)。

答案1

简而言之,要回答主要问题,rsync似乎要写入双倍的字节数,因为它会产生两个进程/线程来进行复制,并且进程之间有一个流数据,另一个从接收进程到目标文件。

我们可以通过更详细地查看strace输出来判断这一点,文件开头的进程 ID 以及调用中的文件描述符编号write可用于区分不同的写入“流”。

据推测,这是为了本地传输可以像远程传输一样工作,只是源和目标位于同一系统上。


使用类似的东西strace -e trace=process,socketpair,open,read,write会显示一些线程产生,在它们之间创建套接字对,以及打开输入和输出文件的不同线程。

与您类似的测试运行:

$ rm test2
$ strace -f -e trace=process,socketpair,open,close,dup,dup2,read,write -o rsync.log rsync -avcz --progress test1 test2
$ ls -l test1 test2
-rw-r--r-- 1 itvirta itvirta 81920004 Jun 21 20:20 test1
-rw-r--r-- 1 itvirta itvirta 81920004 Jun 21 20:20 test2

让我们分别计算每个线程写入的字节数:

$ for x in 15007 15008 15009  ; do echo -en "$x: " ; grep -E "$x (<... )?write"  rsync.log | awk 'BEGIN {FS=" = "} {sum += $2} END {print sum}'  ; done 
15007: 81967265
15008: 49
15009: 81920056

这与上面的理论非常吻合。我没有检查第一个线程写入的其他 40kB 是什么,但我假设它打印进度输出,以及有关同步文件 rsync 的任何元数据需要传输到另一端。


我没有检查,但我建议即使启用了增量压缩,也许 rsync 的“远程”端仍然会完整写出(大部分)文件,从而导致与 cp 大约相同的写入量。 rsync线程之间的传输较小,但最终输出仍然相同。

答案2

默认情况下,出于各种安全原因,rsync 首先创建目标文件的新副本,然后替换它。您可以通过指定--inplace和 来覆盖它--no-whole-file。这告诉 rsync 对目标文件进行就地编辑,接受手册页中记录的各种风险(对于这种情况通常较小)。

相关内容