🧩Delta-Transfer: nur die Unterschiede senden
Wie kann der Sender wissen, was sich geändert hat, wenn er die alte Datei gar nicht kennt? Der Trick von Andrew Tridgell und Paul Mackerras (1996): Der Empfänger beschreibt seine Datei durch Prüfsummen, der Sender sucht diese Stücke in der neuen Datei – an jeder Byte-Position, dank einer Prüfsumme, die sich in O(1) weiterschieben lässt.
🧪Delta-Labor
① Empfänger zerlegt die alte Datei in 10 Blöcke
Jede Farbe = ein Block. Für jeden Block gehen eine schwache 32-Bit-Rollsumme und eine starke Prüfsumme (hier MD5) an den Sender.
| Block | Offset | Länge | schwach | stark (MD5, gekürzt) |
|---|---|---|---|---|
| #0 | 0 | 16 | 2d8c0485 | 3b7325b1159e… |
| #1 | 16 | 16 | 2b2004bb | 9ff44e8eb134… |
| #2 | 32 | 16 | 35750650 | bf138caf5de3… |
| #3 | 48 | 16 | 245804ce | 0d322d9565bb… |
| #4 | 64 | 16 | 364605e9 | 3ffd71c2a6e9… |
| #5 | 80 | 16 | 1fbc0485 | 552e8dd36200… |
| #6 | 96 | 16 | 3186055f | a6553f35b8d1… |
| #7 | 112 | 16 | 369a0616 | ac33022fe478… |
| #8 | 128 | 16 | 38a20634 | 82fdbf62c01b… |
| #9 | 144 | 12 | 1baf041a | 777cf1117a16… |
② Sender schiebt ein 16-Byte-Fenster über die neue Datei
Links vom Fenster ist schon entschieden: Literal oder Farbe des gefundenen Blocks. Rechts: noch offen.
③ Anweisungen an den Empfänger
- KOPIEBlock #0–#3(64 B aus der alten Datei)
- LITERAL„rsync -a kopieren↵3“(19 B)
- KOPIEBlock #5–#9(76 B aus der alten Datei)
④ Was wurde gespart?
Schätzung: Signatur = Blöcke × (4 + 16) Byte, Delta = Literale + 4 Byte je Anweisung. Bei winzigen Dateien lohnt sich der Aufwand nicht – echte rsync-Blöcke sind ≥ 700 Byte, die Signatur ist dann im Verhältnis winzig. Zahlen für Literal/Matched stimmen mit rsync --stats überein (in den Tests gegen rsync 3.5.0 geprüft).
🧮Die rollende Prüfsumme
Für ein Fenster der Länge L ab Position k mit den Bytes X berechnet rsync zwei 16-Bit-Summen:
s1 = ( X[k] + X[k+1] + … + X[k+L-1] ) mod 2^16 s2 = ( L·X[k] + (L-1)·X[k+1] + … + 1·X[k+L-1] ) mod 2^16 schwach = s1 + 2^16 · s2 (32 Bit)
Beim Weiterschieben um ein Byte fällt X[k] heraus und X[k+L] kommt hinzu – ohne alles neu zu addieren:
s1' = s1 − X[k] + X[k+L] s2' = s2 − L·X[k] + s1'
Das ähnelt Adler-32, rechnet aber einfach modulo 216 statt modulo 65521. rsync liest die Bytes dabei als vorzeichenbehaftete char – auch das bildet das Labor nach.
Warum zwei Prüfsummen?
- Schwach = billig und rollbar, wird an jeder Position berechnet, hat aber Kollisionen („Fehlalarme“).
- Stark = teuer, nur bei einem Treffer in der Hash-Tabelle. Aktuelle rsync-Versionen handeln dafür
xxh128aus, ältere Protokolle nutzen MD5 oder MD4. - Zum Schluss prüft der Empfänger eine Prüfsumme über die ganze neue Datei – passt sie nicht, wird die Datei noch einmal übertragen.
Blockgröße
rsync wählt sie je Datei: etwa √Dateigröße, auf ein Vielfaches von 8 abgerundet, mindestens 700 und höchstens 131 072 Byte (Protokoll ≥ 30). Eine 1-MB-Datei bekommt 1000-Byte-Blöcke, eine 100-MB-Datei 10 000-Byte-Blöcke. Mit -B / --block-size lässt sie sich festlegen.
⚡Vorher: Muss die Datei überhaupt übertragen werden?
rsync -a — Größe und Änderungszeit vergleichen. Liest keine Inhalte – extrem schnell, aber blind für Änderungen, die Größe und Zeit nicht verändern.
| Datei | Sender (Größe · Zeit) | Empfänger | Was ist passiert? | Entscheidung |
|---|---|---|---|---|
| foto.jpg | 2048 B · 08:00:00 | 2048 B · 08:00:00 | unverändert | übersprungen Größe und mtime gleich |
| notiz.txt | 13 B · 08:00:00 | 13 B · 08:00:00 | Inhalt geändert, Größe + Zeit zufällig gleich | ⚠ übersprungen! Größe und mtime gleich |
| config.ini | 300 B · 09:00:00 | 300 B · 08:00:00 | nur „touch“ – Inhalt gleich, Zeit neuer | ↗ übertragen mtime weicht 3600 s ab |
| log.txt | 5120 B · 08:01:00 | 4096 B · 08:00:00 | angehängt – größer | ↗ übertragen Größe 5120 ≠ 4096 |
| usb-stick.doc | 800 B · 08:00:01 | 800 B · 08:00:00 | FAT-Ziel: Zeit um 1 s gerundet | ↗ übertragen mtime weicht 1 s ab |
| neu.pdf | 999 B · 08:00:00 | — | neu | ↗ übertragen fehlt beim Empfänger |
-c prüfen – oder mit rsync -anc --itemize-changes nur anzeigen lassen.--whole-file ein: Die Platte ist schneller als jede Prüfsummenrechnerei. Mit --no-whole-file lässt sich der Algorithmus trotzdem erzwingen.