Warum gibt es eine große Diskrepanz zwischen den von du und ls angegebenen Dateigrößen?

2

Auf einem Server habe ich ein Verzeichnis /opt/kafka/data/topics.

$ du -hs /opt/kafka/data/topics
52M     /opt/kafka/data/topics

Wenn ich dieses Verzeichnis wie tar

$ tar czfv /tmp/topics.tar.gz /opt/kafka/data/topics

Ich bekomme eine Dateigröße, die Sinn macht

$ ls -alh /tmp/topics.tar.gz
-rw-r--r-- 1 user user  11M Jan 12 15:15 kafka

Wenn ich jedoch topics.tar.gzauf meinen lokalen OS X-Computer herunterlade und ihn extrahiere, belegt er 10 GB!


Bei /opt/kafka/data/topicsgenauerer Betrachtung der Inhalte auf dem Server ist mir aufgefallen, dass dementsprechend lsviele 10MB-Dateien enthalten sind:

$ find /opt/kafka/data -type f -exec ls -alh {} \;
... [output]
-rw-r--r-- 1 user user 10M Jan 12 02:45 /opt/kafka/data/topics/user-entities-KTABLE-REDUCE-STATE-STORE-0000000178-changelog-1/00000000000000000000.index
-rw-r--r-- 1 user user 10M Jan 12 02:45 /opt/kafka/data/topics/user-entities-KSTREAM-KEY-SELECT-0000000123-repartition-2/00000000000000000012.index
... [and many more]

du meldet, dass jede dieser 10 MB-Dateien 0 Byte groß ist:

$ du -h /opt/kafka/data/topics/user-entities-KTABLE-REDUCE-STATE-STORE-0000000178-changelog-1/00000000000000000000.index
0       /opt/kafka/data/topics/user-entities-KTABLE-REDUCE-STATE-STORE-0000000178-changelog-1/00000000000000000000.index

Also, was ist los? Offensichtlich fehlt mir hier etwas:

  • dumeldet insgesamt 52 Millionen. Dies ist sinnvoll, da das /opt/kafka/datagemountete Gerät nur 5 GB hat, dfnur 2% voll ist und alles noch funktioniert.
  • targzipst den Inhalt auf 10M. Das macht auch Sinn.
  • ls meldet, dass sich viele der Dateien auf 10 MB Festplatte befinden, und wenn ich das Archiv extrahiere, erhalte ich 10 GB.
  • du meldet, dass jede dieser Dateien 0 Byte groß ist.
  • mount meldet das /dev/sdc on /opt/kafka/data type ext4 (rw,relatime,data=ordered)

Nichts passt zusammen. Gibt es eine Art transparente Komprimierung auf der Festplatte, die mir nicht bekannt ist?

Dmitry Minkovsky
quelle
Mehrere Hardlinks zu derselben Datei im Quellverzeichnis? Sparse Dateien?
Kamil Maciorowski
@KamilMaciorowski keine Hardlinks; Ja, die 10-MB-Dateien (wie von gemeldet ls) sind spärlich. Sie werden von als 0 Bytes gemeldet duund sind in der Tat leer
Dmitry Minkovsky
Wie wäre es mit tar --sparseOption beim Erstellen des Archivs? Hilft es? Link .
Kamil Maciorowski
Helfen mit was? Das Problem ist nicht, dass der Teer groß ist, wenn ich ihn erstelle. Der Teer ist ziemlich klein. Das Problem ist, dass diese 10-MB-Sparse-Dateien auf der Festplatte 0 Byte zu belegen scheinen. Wie kann das sein? Gibt es eine Komprimierung auf Dateisystemebene? Warum werden ls10 MB gemeldet, aber du0 Byte?
Dmitry Minkovsky
Obwohl ... my man tarunter OS X eine Option -Szum Extrahieren enthält: (x mode only) Extract files as sparse files. For every block on disk, check first if it contains only NULL bytes and seek over it otherwise. This works similiar to the conv=sparse option of dd.Dies kann hilfreich sein.
Dmitry Minkovsky

Antworten:

3

Aufgrund der Diskussion in den Kommentaren sind alle Dateien spärlich. Diese Art von Dingen verwirrt viele Leute, wenn sie sich zum ersten Mal damit beschäftigen, also fühle dich nicht schlecht.

Was ist hier eigentlich mit den von lsund gemeldeten Werten los du?

Dies lässt sich am einfachsten anhand eines Beispiels erklären.

Angenommen, Sie erstellen eine leere Datei und schreiben dann 1 MB Daten beginnend am Anfang darauf. Die resultierende Datei hat eine Größe von 1 MB und belegt 1 MB Festplattenspeicher. Beide lsund dugeben dieselbe Größe von 1 MB für die Datei an.

Sagen Sie stattdessen, Sie erstellen eine leere Datei und rufen dann seek()auf, um 1 MB in die Datei zu verschieben, und schreiben dann ein Byte. Die resultierende Datei scheint 1 MB + 1 Byte lang zu sein, enthält jedoch nur 1 Byte Daten.

Auf älteren Dateisystemen hätte das Schreiben dieser 1-Byte-Datei sehr lange gedauert, da das Betriebssystem 1 MB Nullbyte ausschrieb, bevor es die letzten 1 Byte der tatsächlichen Daten ausschrieb.

Diese Ineffizienz (sowohl in Bezug auf die Zeit zum Erstellen der Datei als auch auf den auf der Festplatte belegten Speicherplatz) ist der Ort, an dem Dateien mit geringer Dichte eingehen Vermerken Sie in den Metadaten dieses Dateisystems, dass die Region von 0 bis 1 MB leer ist, und speichern Sie dann nur das einzelne Byte, das Sie geschrieben haben. Infolgedessen scheint die Datei 1 MB + 1 Byte lang zu sein, aber auf der Festplatte nimmt sie nur 1 Byte ein. Wenn diese Datei gelesen wird, werden alle Bereiche, die das Betriebssystem als leer markiert hat, nur als Null-Bytes zurückgelesen (so dass sich Benutzerprogramme von der ersten Datei nicht unterscheiden).

Hier liegt die Diskrepanz zwischen den von lsund gemeldeten Werten du. Standardmäßig wird lsdie scheinbare Größe von Dateien gemeldet (d. H., Wie viele Daten würden Sie lesen, wenn Sie die Datei im ersten Byte und bis zum Ende lesen würden), während duder tatsächlich von der Datei belegte Speicherplatz auf der Festplatte gemeldet wird (normalerweise ohne andere platzsparende Tricks des Betriebssystems wie transparente Komprimierung). dustimmt dfin diesem Fall zu, da dfnur der tatsächlich auf der Festplatte belegte Speicherplatz gemeldet wird.

Wenn Sie diesen ls -lBefehl in ändern ls -ls, erhalten Sie eine zusätzliche Spalte, in der die tatsächliche Größe der Dateien auf der Festplatte angegeben ist, mit der Sie übereinstimmen sollten du.

Austin Hemmelgarn
quelle
Ich fühle mich nicht schlecht, keine Sorge;) Danke, dass du auf den -s-Schalter hingewiesen hast. Ich werde das untersuchen.
Dmitry Minkovsky