1

На сервере у меня есть каталог /opt/kafka/data/topics .

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

Когда я tar этот каталог, как

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

Я получаю размер файла, который имеет смысл

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

Однако, когда я загружаю topics.tar.gz на свой локальный компьютер OS X и распаковываю его, он занимает 10 ГБ!


При более внимательном изучении содержимого /opt/kafka/data/topics на сервере я заметил, что согласно ls он содержит много файлов размером 10 МБ:

$ 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 сообщает, что каждый из этих файлов размером 10 МБ имеет размер 0 байт:

$ 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

Так, что происходит? Очевидно, я что-то здесь упускаю:

  • du сообщает 52M всего. Это имеет смысл, поскольку устройство, на котором монтируется /opt/kafka/data , занимает всего 5 ГБ, df сообщает, что оно заполнено только на 2% и все еще работает.
  • tar gzips содержимое до 10M. Это тоже имеет смысл.
  • ls сообщает, что многие файлы имеют размер 10 МБ на диске, и когда я распаковываю архив, я получаю 10 ГБ.
  • du сообщает, что каждый из этих файлов имеет размер 0 байт.
  • mount отчеты, что /dev/sdc on /opt/kafka/data type ext4 (rw,relatime,data=ordered)

Ничего не складывается. Есть ли какое-то прозрачное сжатие на диске, о котором я не знаю?

1 ответ1

2

Судя по обсуждению в комментариях, все файлы редки. Подобные вещи действительно смущают многих людей, когда они впервые сталкиваются с этим, так что не расстраивайтесь.

Что на самом деле происходит со значениями, указанными ls и du?

Это легче всего объяснить на примере.

Допустим, вы создали пустой файл, а затем записали в него 1 МБ данных, начиная с самого начала. Результирующий файл будет иметь размер 1 МБ и занимать 1 МБ на диске. И ls и du сообщат об одном и том же размере 1 МБ для файла.

Теперь, скажем, вместо этого вы создаете пустой файл, а затем вызываете seek() чтобы переместить 1 МБ в файл, а затем записываете один байт. Результирующий файл будет иметь размер 1 МБ + 1 байт, но на самом деле он содержит только 1 байт данных.

В более старых файловых системах второй файл занял бы очень много времени, чтобы записать эти 1 байт данных, поскольку ОС была бы занята записью 1 МБ нулевых байтов, прежде чем записать эти последние 1 байт фактических данных.

Из-за этой неэффективности (как с точки зрения времени создания файла, так и места, используемого на диске) возникают редкие файлы. Вместо того, чтобы записывать эти 1 МБ нулевых байтов, ОС, поддерживающая разреженные файлы (как и все современные системы UNIX), будет аннотировать в метаданных этой файловой системы, что область формы 0-1 МБ пуста, а затем хранить только тот единственный байт, который вы написали. В результате файл будет иметь размер 1 МБ + 1 байт, но на диске он займет всего 1 байт. Кроме того, когда что-то идет на чтение этого файла, любые регионы, аннотированные ОС как пустые, будут просто считываться как нулевые байты (так что это не похоже на программы пользователя из первого файла).

Отсюда и расхождение между значениями, сообщаемыми ls и du . По умолчанию ls сообщает о кажущемся размере файлов (то есть о том, сколько данных вы бы прочитали, если бы начали читать файл с первого байта и полностью прочитать до конца), а du сообщает о фактическом пространстве, используемом на диске, файл (обычно не включая другие приемы экономии пространства, выполняемые ОС, такие как прозрачное сжатие). В этом случае du соглашается с df потому что df сообщает только количество места, которое фактически физически используется на диске.

Изменив эту команду ls -l на ls -ls , вы получите дополнительный столбец, показывающий фактический размер файлов на диске, который должен соответствовать du .

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .