tại sao rsync không thực hiện chuyển delta


7

Tôi có tệp nhị phân có khoảng 77 MB:

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

Tôi đã chơi với rsyncvà đó là tính năng thuật toán delta để xem nó hoạt động như thế nào. Ý tưởng là tạo ra sự khác biệt nhỏ trong tệp nhị phân và xem có bao nhiêu dữ liệu được truyền bằng một số phương pháp. Đối với những mục đích đó, tôi đã tạo ra kịch bản rất đơn giản:

#!/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

Sau đó, tôi có vòng lặp sau để đánh giá kết quả:

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

Đây là kết quả:

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
###########

Từ năm thí nghiệm đó, chỉ có hai là rõ ràng với tôi:

  1. cpghi số lượng byte tương đương với kích thước của tệp gốc ( rw_cp.log).
  2. rsyncsử dụng thuật toán delta khi đích ở xa (qua mạng) ( rw_rsync_remote.log)

Và đây là những điều không rõ ràng với tôi:

  1. Tại sao gọi rsynctrên cả hai srcdsttrên localhostghi khoảng hai lần byte bằng kích thước của tệp gốc? ( rw_rsync_local_default.log)
  2. Tại sao --no-Wtùy chọn rsynckhông chỉ chuyển delta cho srcdsttrên localhostnhư đã nêu ở đây và tại sao nó vẫn chuyển toàn bộ tệp? ( rw_rsync_local_delta_enabled.log)
  3. Phần thưởng: Tại sao scpchuyển khoảng hai lần byte như kích thước tệp gốc? Tôi hiểu rằng có một số mã hóa nhưng hai lần có vẻ lớn đối với tôi ( rw_scp.log).

Câu trả lời:


4

Để trả lời ngắn gọn câu hỏi chính, rsyncdường như viết gấp đôi số byte, bởi vì nó sinh ra hai tiến trình / luồng để thực hiện sao chép và có một luồng dữ liệu giữa các tiến trình và một luồng khác từ quá trình nhận đến tệp đích.

Chúng ta có thể nói điều này bằng cách xem stracechi tiết đầu ra, ID quá trình ở phần đầu của tệp và cũng writecó thể sử dụng số mô tả tệp trong các cuộc gọi để nói các "luồng" ghi khác nhau.

Có lẽ, điều này là để chuyển cục bộ có thể hoạt động giống như chuyển từ xa, chỉ có nguồn và đích trên cùng một hệ thống.


Sử dụng một cái gì đó giống như strace -e trace=process,socketpair,open,read,writesẽ hiển thị một số luồng sinh ra, cặp socket được tạo giữa chúng và các luồng khác nhau mở các tệp đầu vào và đầu ra.

Chạy thử tương tự như của bạn:

$ 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

Chúng ta hãy đếm một số byte được viết riêng cho từng luồng:

$ 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

Mà phù hợp khá nhiều với lý thuyết trên. Tôi đã không kiểm tra 40kB khác được viết bởi luồng đầu tiên là gì, nhưng tôi sẽ cho rằng nó in kết quả đầu ra và bất kỳ siêu dữ liệu nào về rsync tệp được đồng bộ hóa cần chuyển sang đầu kia.


Tôi đã không kiểm tra, nhưng tôi sẽ đề nghị rằng ngay cả khi đã bật nén delta, có lẽ phần cuối "rsync" vẫn ghi ra (hầu hết) tệp đầy đủ, dẫn đến số lượng ghi tương đương với cp. Việc chuyển giữa các luồng rsync nhỏ hơn, nhưng đầu ra cuối cùng vẫn giống nhau.


1
Và tương tự scptạo ra một sshquy trình con để thực hiện giao thức SSH thực tế (bắt tay, mã hóa và MAC). Do đó, phụ huynh đọc tệp và ghi qua đường ống cho con, đồng thời ghi đồng hồ 'tiến độ' vào thiết bị đầu cuối, khá nhỏ; đứa trẻ đọc đường ống và đọc và ghi ổ cắm cho giao thức SSH, thường thêm 1-2k khởi động và, có thể là 1% vào dữ liệu.
dave_thndry_085

@ilkkachu Tôi đã cố gắng để nhận được byte bằng văn bản cho mỗi đứa trẻ nhưng có thể có điều gì đó không ổn với regrec. Mã đã thử:for x in $(awk '{print $1}' rsync.log | sort | uniq); do; echo -en "$x: "; grep -E "$x (<... )?write" rsync.log | awk 'BEGIN {FS=" = "} {sum += $2} END {print sum}'; done
Wakan Tanka

2

Theo mặc định, trước tiên, rsync tạo một bản sao mới của tệp đích và sau đó thay thế nó, vì nhiều lý do an toàn. Bạn có thể ghi đè lên điều này bằng cách chỉ định --inplacecùng với --no-whole-file. Điều này yêu cầu rsync thực hiện chỉnh sửa tại chỗ tệp mục tiêu, chấp nhận các rủi ro khác nhau (thường là nhỏ đối với tình huống này) như được ghi trong trang hướng dẫn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.