เหตุใด rsync จึงไม่ใช้การถ่ายโอนเดลต้าสำหรับไฟล์เดียวทั่วทั้งเครือข่าย


15

ฉันได้ดูคำถามนี้และคำถามนี้แต่พวกเขาดูเหมือนจะไม่สามารถบอกอาการที่ฉันเห็นได้

ฉันมีล็อกไฟล์ขนาดใหญ่ (ประมาณ 600 MB) ที่ฉันพยายามถ่ายโอนข้ามเครือข่ายเซลลูลาร์ เพราะมันเป็นแฟ้มบันทึกมันเป็นเพียงการผนวกเข้ากับ (แม้ว่ามันจะเป็นจริงในฐานข้อมูล SQLite มีเพียง INSERT การดำเนินการเพื่อให้มันไม่ได้ค่อนข้างง่ายเหมือนที่ แต่มีข้อยกเว้นของสุดท้าย 4k หน้า (หรืออาจจะเป็น น้อย) ไฟล์จะเหมือนกันทุกครั้งมันเป็นสิ่งสำคัญที่จะต้องทำการเปลี่ยนแปลงเท่านั้น

แต่เมื่อฉันทำการทดสอบผ่านการเชื่อมต่อที่ไม่มีการตรวจสอบ (เช่นฮอตสปอต wifi ฟรี) ฉันไม่เห็นการถ่ายโอนข้อมูลที่เร่งความเร็วหรือลดลงที่สังเกตหรือรายงาน ผ่านการเชื่อมต่อ WiFi ช้าฉันเห็นตามคำสั่งของ 1MB / s หรือน้อยกว่ารายงานว่าการถ่ายโอนจะใช้เวลาเกือบ 20 นาที ผ่านการเชื่อมต่อ WiFi ที่รวดเร็วฉันเห็นความเร็วที่เร็วขึ้นเหมือนกัน แต่ไม่มีรายงานการเร่งความเร็วและความพยายามครั้งที่สองในการถ่ายโอน

คำสั่ง (ฆ่าเชื้อเพื่อลบข้อมูลที่ละเอียดอ่อน) ที่ฉันใช้อยู่คือ:

rsync 'ssh -p 9999' --progress LogFile michael@my.host.zzz:/home/michael/logs/LogFile

ผลลัพธ์ที่ฉันได้รับในตอนท้ายดูเหมือนว่า:

LogFile
    640,856,064 100%   21.25MB/s   0:00:28 (xfr$1, to-chk=0/1)

ไม่มีการเอ่ยถึงการเร่งความเร็วใด ๆ

ฉันสงสัยว่าปัญหาอาจเป็นหนึ่งในสิ่งต่อไปนี้:

  • ฉันไม่มีตัวเลือกบรรทัดคำสั่ง อย่างไรก็ตามการอ่านหน้าคนใหม่ดูเหมือนว่าจะแนะนำว่าการถ่ายโอนเดลต้าเปิดใช้งานตามค่าเริ่มต้น: ฉันเห็นเฉพาะตัวเลือกสำหรับการปิดใช้งาน
  • ฉันใช้ rsync บน ssh (บนพอร์ตที่ไม่ได้มาตรฐาน) เนื่องจากเซิร์ฟเวอร์ที่อยู่หลังไฟร์วอลล์ที่อนุญาตให้ใช้ ssh เท่านั้น ฉันไม่เห็นอะไรเลยว่าการโอนย้ายเดลต้าจะไม่ทำงานหาก rsync daemon ไม่ทำงาน ฉันพยายามใช้สัญกรณ์ "::" แทนที่จะเป็น ":" แต่หน้าคนไม่ชัดเจนมากเกี่ยวกับสิ่งที่ "โมดูล" คืออะไรและคำสั่งของฉันถูกปฏิเสธสำหรับการระบุโมดูลที่ไม่ถูกต้อง

ฉันได้ตัดสิ่งต่อไปนี้ออกแล้ว:

  • การถ่ายโอนเดลต้าไม่ได้ดำเนินการบนเครือข่ายท้องถิ่น ตัดออกเพราะฉันพยายามทำการโอนผ่านทางอินเทอร์เน็ต
  • ค่าใช้จ่ายเนื่องจากการคำนวณ checksum ฉันได้เห็นพฤติกรรมนี้ทั้งบนการเชื่อมต่อ Wifi ที่ช้าและช้าและอัตราการถ่ายโอนดูเหมือนจะไม่ถูกคำนวณ

1
but with the exception of the last 4k page (or maybe a few) the file is identical each time. คุณยืนยันด้วยcmpหรือไม่ หรือดีกว่ามีxdeltaหรืออะไร หากคุณต้องการลดขนาดการถ่ายโอนให้เก็บเวอร์ชันเก่าและใหม่ไว้ในเครื่องเพื่อให้คุณสามารถคำนวณเลขฐานสองที่น้อยที่สุดในพื้นที่ การทำสิ่งนี้ในระดับบันทึกฐานข้อมูลแทนระดับไฟล์ไบนารีน่าจะดีกว่านี้อย่างที่ Derobert แนะนำ
Peter Cordes

1
นอกจากนี้คุณสามารถใช้rsync --statsและ-v -vได้รับสถิติ verbose มากยิ่งขึ้น Rsync จะบอกคุณว่ามีการจับคู่กับข้อมูลที่ไม่ตรงกันเท่าไร
Peter Cordes

คำตอบ:


27

สรุป

ฐานข้อมูลมักจะเก็บข้อมูลเมตาจำนวนมากข้อมูลองค์กรและอื่น ๆ ส่วนแทรกนั้นไม่น่าจะเป็นผนวกอย่างง่ายเช่นเดียวกับที่ใช้กับไฟล์ข้อความ การทดสอบ SQLite แสดงว่ามันทำงานแบบนั้นทั้งในโหมด WAL และไม่ใช่ WAL สิ่งนี้ทำให้ rsync ต้องซิงค์ข้อมูลมากกว่าที่คุณคาดไว้มาก คุณสามารถลดค่าโสหุ้ยนี้ได้โดยใช้ค่าต่ำ--block-size(ในการคำนวณค่าโสหุ้ยเพิ่มเติมและการโอนย้าย checksums)

วิธีที่ดีกว่าน่าจะเป็นไปได้ที่จะทิ้งเร็กคอร์ดใหม่เป็นดัมพ์ SQL บีบอัดและโอนย้าย อีกวิธีหนึ่งดูเหมือนจะมีโซลูชันการจำลองแบบหลายอย่างสำหรับ SQLite คุณสามารถใช้หนึ่งในนั้น

roaimaแนะนำอย่างน้อยที่สุดคุณอาจใช้การถ่ายโอนข้อมูล SQL แบบเต็มบีบอัดโดยใช้gzip --rsyncableแล้ว rsync นั้น ฉันน่าจะลองดูว่าเป็นเดลต้าตัวเล็ก ๆ หรือเปล่า

รายละเอียด

สิ่งที่คุณพยายามจะทำงาน ฉันจะเพิ่ม--partialตัวเลือก rsync ของคุณเป็นการส่วนตัวในกรณีที่ตรวจพบไฟล์ที่กำลังเติบโตเป็นการถ่ายโอนบางส่วน --statsนอกจากนี้คุณยังจะได้รับการถ่ายโอนสถิติที่ดีขึ้นด้วย

สิ่งที่สองที่ต้องตรวจสอบคือถ้า SQLite สัมผัสได้เพียงไม่กี่หน้าเท่านั้นจริงๆแล้วฉันไม่แปลกใจถ้ามันกำลังเขียนหน้าทั่วทั้งแฟ้ม วิธีหนึ่งที่รวดเร็วในการตรวจสอบคือใช้cmp -lกับสองเวอร์ชันดูว่ามีการเปลี่ยนแปลงหน้าอื่นนอกเหนือจากหน้าสุดท้ายหรือไม่ โปรดจำไว้ว่าrsyncแนวคิดของ "หน้า" / บล็อกนั้นแตกต่างจากของ SQLite คุณสามารถเปลี่ยนของ rsync --block-sizeผ่าน การลดอาจช่วยได้

แก้ไข:ฉันทำการทดสอบอย่างรวดเร็วด้วย SQLite ถึงแม้จะมีหน้า 32k การเพิ่มรายการบันทึกที่เขียนบนหน้าเว็บทุกหน้า รายละเอียดด้านล่าง

แก้ไข 2 : ดูเหมือนว่าจะดีกว่าในโหมด WAL แม้ว่าคุณจะยังคงมีค่าใช้จ่ายจำนวนมากอาจมาจากจุดตรวจสอบ

แก้ไข 3 : นอกจากนี้ยังเป็นการดียิ่งข้อมูลที่คุณเพิ่มต่อการถ่ายโอน - ฉันคิดว่ามันอาจขีดบล็อกบางอย่างซ้ำแล้วซ้ำอีก ดังนั้นคุณจะถ่ายโอนบล็อกชุดเดียวกันโดยไม่คำนึงว่ามันเขียนถึงพวกเขาครั้งเดียวหรือร้อยครั้ง

BTW: สำหรับการย่อขนาดการถ่ายโอนคุณอาจทำได้ดีกว่า rsync ตัวอย่างเช่นการดัมพ์ SQL ของเร็กคอร์ดใหม่ตั้งแต่การถ่ายโอนครั้งล่าสุดที่ทำงานผ่านxz --best(หรือแม้กระทั่งgzip) อาจเป็นบิตที่มีขนาดเล็กกว่าเล็กน้อย

ทดสอบ SQLite ด่วน

schema:

CREATE TABLE log (id integer primary key not null, ts integer not null, app text not null, message text not null);
CREATE INDEX log_ts_idx on log(ts);
CREATE INDEX log_app_idx on log(app);

โปรแกรม Perl:

use 5.022;
use DBI;

my $DBH = DBI->connect('dbi:SQLite:test.db', '', '', {RaiseError => 1, AutoCommit => 0})
    or die "connect...";

my @apps = (
    '[kthreadd]',        '[ksoftirqd/0]',
     # there were 191 of these
    '[kworker/5:0H]',
);

my @messages = <DATA>;

(my $curr_time) = $DBH->selectrow_array(<<QUERY);
    SELECT COALESCE(MAX(ts),978307200) FROM log
QUERY

my $n_apps = @apps;
my $n_msgs = @messages;
say "Apps: $n_apps";
say "Messages: $n_msgs";
say 'Start time: ', scalar gmtime($curr_time), ' UTC';

my $sth = $DBH->prepare(<<QUERY);
    INSERT INTO log(ts, app, message) VALUES (?, ?, ?)
QUERY

for (my $i = 0; $i < 10_000; ++$i) {
    $sth->execute(int($curr_time), $apps[int rand $n_apps], $messages[int rand $n_msgs]);
    $curr_time += rand 0.1;
}
$DBH->commit;

__DATA__
microcode: CPU0 microcode updated early to revision 0x19, date = 2013-06-21
Linux version 4.5.0-2-amd64 (debian-kernel@lists.debian.org) (gcc version 5.3.1 20160528 (Debian 5.3.1-21) ) #1 SMP Debian 4.5.5-1 (2016-05-29)

มีข้อความบันทึกตัวอย่างมากขึ้น (2076)

การตรวจสอบว่าหน้าใดมีการเปลี่ยนแปลง:

cp test.db test.db.old
perl test.pl
cmp -l test.db.old test.db | perl -n -E '/^\s*(\d+) / or die "wtf"; $bucket{int $1/32768} = 1; END { say join "\n", sort( { $a <=> $b } keys %bucket) }'
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.