Warum verwendet rsync keine Delta-Übertragungen für eine einzelne Datei in einem Netzwerk?

15

Ich habe mir diese Frage und diese Frage angeschaut , aber sie scheinen nicht die Symptome anzusprechen, die ich sehe.

Ich habe eine große Protokolldatei (ca. 600 MB), die ich über ein Mobilfunknetz übertragen möchte. Da es sich um eine Protokolldatei handelt, wird sie nur angehängt (obwohl sie sich tatsächlich in einer SQLite-Datenbank befindet, in der nur INSERT ausgeführt wird, ist sie also nicht ganz so einfach, sondern mit Ausnahme der letzten 4k-Seite (oder vielleicht einer wenige) Die Datei ist jedes Mal identisch. Es ist wichtig, dass nur die Änderungen (und die zu übertragenden Prüfsummen) tatsächlich gesendet werden, da die Datenverbindung gemessen wird.

Wenn ich jedoch einen Test über eine nicht gemessene Verbindung durchführe (z. B. einen kostenlosen WLAN-Hotspot), sehe ich keine beobachtete oder gemeldete Beschleunigung oder Verringerung der Datenübertragung. Über eine langsame WiFi-Verbindung sehe ich in der Größenordnung von 1 MB / s oder weniger und berichte, dass die Übertragung fast 20 Minuten dauern wird. Über eine schnelle WLAN-Verbindung sehe ich eine einheitlich schnellere Geschwindigkeit, aber keinen Bericht über die Geschwindigkeitssteigerung, und ein zweiter Übertragungsversuch (der jetzt schneller sein sollte, da die beiden Dateien identisch sind) zeigt jetzt keinen Unterschied.

Der Befehl (bereinigt, um vertrauliche Informationen zu entfernen), den ich verwende, lautet:

rsync 'ssh -p 9999' --progress LogFile [email protected]:/home/michael/logs/LogFile

Die Ausgabe, die ich am Ende bekomme, sieht folgendermaßen aus:

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

Es gibt keine Erwähnung irgendeiner Art von Beschleunigung.

Ich vermute, das Problem könnte eines der folgenden sein:

  • Mir fehlt eine Befehlszeilenoption. Das erneute Lesen der Manpage scheint jedoch darauf hinzudeuten, dass Delta-Übertragungen standardmäßig aktiviert sind: Es werden nur Optionen zum Deaktivieren angezeigt.
  • Ich verwende rsync über ssh (auch auf einem nicht standardmäßigen Port), da sich der Server hinter einer Firewall befindet, die nur ssh zulässt. Ich habe nicht explizit festgestellt, dass Delta-Übertragungen nicht funktionieren, wenn der rsync-Dämon nicht ausgeführt wird. Ich habe versucht, die "::" - Notation anstelle von ":" zu verwenden, aber in der Manpage ist nicht klar, was ein "Modul" ist, und mein Befehl wird wegen der Angabe eines ungültigen Moduls abgelehnt.

Folgendes habe ich ausgeschlossen:

  • Delta-Übertragungen werden nicht in einem lokalen Netzwerk durchgeführt. Ausgeschlossen, weil ich versuche, die Übertragung über das Internet durchzuführen
  • Gemeinkosten aufgrund von Prüfsummenberechnung. Ich habe dieses Verhalten sowohl bei einer schnellen als auch bei einer langsamen WLAN-Verbindung festgestellt, und die Übertragungsrate scheint nicht rechnergebunden zu sein.
Michael
quelle
1
but with the exception of the last 4k page (or maybe a few) the file is identical each time. Haben Sie das tatsächlich überprüft cmp? Oder besser mit xdeltaoder so? Wenn Sie die Übertragungsgröße wirklich minimieren möchten, behalten Sie die alte und die neue Version lokal bei, damit Sie lokal (mit etwas anderem als rsync) eine minimale Binärdifferenz berechnen und diese einfach senden können, ohne Prüfsummen über die gemessene Verbindung senden zu müssen. Dies auf Datenbankdatensatzebene anstelle der Binärdateiebene zu tun, ist wahrscheinlich sogar noch besser, wie derobert vorschlägt.
Peter Cordes
1
Sie hätten auch verwenden können rsync --stats, -v -vum noch ausführlichere Statistiken zu erhalten. Rsync teilt Ihnen mit, wie viele übereinstimmende und nicht übereinstimmende Daten vorhanden waren.
Peter Cordes

Antworten:

27

Zusammenfassung

Datenbanken enthalten in der Regel viele Metadaten, Organisationsdaten usw. Es ist sehr unwahrscheinlich, dass eine Einfügung ein einfacher Anhang ist, wie dies bei einer Textdatei der Fall wäre. Das Testen von SQLite zeigt, dass es sich sowohl im WAL- als auch im Nicht-WAL-Modus so verhält. Dies führt dazu, dass rsync viel mehr Daten synchronisieren muss, als Sie erwarten. Sie können diesen Overhead etwas reduzieren, indem Sie einen niedrigen verwenden --block-size(auf Kosten von mehr Overhead-Computing und der Übertragung von Prüfsummen).

Ein besserer Ansatz ist wahrscheinlich, neue Datensätze als SQL-Dump auszugeben, zu komprimieren und zu übertragen. Alternativ scheint es mehrere Replikationslösungen für SQLite zu geben, von denen Sie eine verwenden könnten.

roaima schlägt vor, zumindest einen vollständigen SQL- Speicherauszug zu erstellen , ihn mit zu komprimieren gzip --rsyncableund dann mit rsync zu synchronisieren. Ich nehme an, es ist einen Test wert, um zu sehen, ob das Delta klein genug ist.

Einzelheiten

Was Sie versuchen, sollte funktionieren. Ich würde --partialIhre rsync-Optionen persönlich erweitern , nur für den Fall, dass die wachsende Datei irgendwie als Teilübertragung erkannt wird. Sie können auch bessere Transferstatistiken mit erhalten --stats.

Die zweite zu überprüfende Sache ist, ob SQLite wirklich nur ein paar Seiten berührt - ehrlich gesagt, wäre ich nicht überrascht, wenn es Seiten über die gesamte Datei schreibt. Eine schnelle Möglichkeit, dies zu überprüfen, besteht darin, cmp -lzwei Versionen zu verwenden. Überprüfen Sie, ob auf anderen Seiten als den letzten Änderungen vorgenommen wurden. Denken Sie daran, dass sich rsyncdie Vorstellung von einer "Seite" / einem Block von der von SQLite unterscheidet. Sie können rsync über ändern --block-size. Eine Reduzierung könnte helfen.

Edit: Ich habe einen Schnelltest mit SQLite gemacht. Sogar mit 32.000 Seiten können Sie eine Reihe von Protokolleinträgen auf jeder Seite hinzufügen . Details unten.

Bearbeiten 2 : Es scheint besser im WAL-Modus zu sein, obwohl Sie immer noch eine Menge Overhead benötigen, wahrscheinlich vom Checkpoint aus.

Bearbeiten 3 : Es ist auch besser, je mehr Daten Sie pro Übertragung hinzufügen. Vermutlich kritzelt es bestimmte Blöcke immer und immer wieder. Sie übertragen also denselben Satz von Blöcken, unabhängig davon, ob er einmal oder hundertmal an sie geschrieben wurde.

Übrigens: Um die Übertragung zu minimieren, können Sie wahrscheinlich viel besser als rsync. Beispielsweise wäre ein SQL-Speicherauszug neuer Datensätze seit dem letzten Durchlauf xz --best(oder sogar gzip) wahrscheinlich ein gutes Stück kleiner.

Schneller SQLite-Test

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-Programm:

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)

Es gab viel mehr Beispielprotokollnachrichten (2076).

Prüfen, für welche Seiten sich etwas geändert hat:

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) }'
derobert
quelle