Назад | Перейти на главную страницу

Эффективное удаление более 10 млн файлов из ZFS

Я написал программу с ошибками, которая случайно создала около 30 миллионов файлов в / tmp. (Ошибка появилась несколько недель назад, и она создавала пару подкаталогов в секунду.) Я мог переименовать / tmp в / tmp2, и теперь мне нужно удалить файлы. Система - FreeBSD 10, корневая файловая система - zfs.

Тем временем один из дисков в зеркале вышел из строя, и я его заменил. Накопитель имеет два SSD-диска по 120 ГБ.

Вот вопрос: замена жесткого диска и перенаправление всего массива заняли менее часа. Удаление файлов / tmp2 - отдельная история. Я написал другую программу для удаления файлов, и она может удалять только 30-70 подкаталогов в секунду. На удаление всех файлов уйдет 2-4 дня.

Как это возможно, что восстановление всего массива занимает час, а удаление с диска - 4 дня? Почему у меня такая плохая производительность? 70 удалений в секунду кажутся очень плохой производительностью.

Я мог бы удалить inode для / tmp2 вручную, но это не освободит место, верно?

Может это проблема с zfs, жесткими дисками или чем-то еще?

Удаление в ZFS стоит дорого. Тем более, если в файловой системе включена дедупликация (поскольку разыменование дедуплицированных файлов обходится дорого). Снимки тоже могут усложнить ситуацию.

Возможно, вам лучше удалить /tmp каталог вместо данных, содержащихся внутри.

Если /tmp файловая система ZFS, удалите ее и создайте заново.

Как это возможно, что восстановление всего массива занимает час, а удаление с диска - 4 дня?

Рассмотрим офисное здание.

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

Снос всего здания с помощью RDX - это целая партия быстрее, но следующий клиент вполне скорее всего, будет жаловаться на сквозняк.

Здесь происходит ряд вещей.

Во-первых, все современные дисковые технологии оптимизированы для массовой передачи. Если вам нужно переместить 100 МБ данных, они сделают это намного быстрее, если будут находиться в одном непрерывном блоке, а не разбросаны повсюду. Здесь очень помогают SSD, но даже они предпочитают данные в непрерывных блоках.

Во-вторых, перенос обновлений является довольно оптимальным для дисковых операций. Вы читаете массивный непрерывный фрагмент данных с одного диска, выполняете на нем несколько быстрых операций ЦП, а затем перезаписываете его в другом большом непрерывном фрагменте на другой диск. Если на полпути пропадет питание, ничего страшного - вы просто проигнорируете любые данные с неверными контрольными суммами и продолжите работу как обычно.

В-третьих, удаление файла очень медленно. ZFS особенно плох, но практически все файловые системы медленно удаляются. Они должны изменить большое количество различных фрагментов данных на диске и правильно рассчитать время (то есть ждать), чтобы файловая система не была повреждена в случае сбоя питания.

Как это возможно, что восстановление всего массива занимает час, а удаление с диска - 4 дня?

Ресилверинг - это то, с чем диски действительно справляются, а удаление - это то, с чем диски работают медленно. Для каждого мегабайта диска вам нужно выполнить лишь небольшую перенастройку. У вас может быть тысяча файлов в этом пространстве, которые необходимо удалить.

70 удалений в секунду кажется очень плохой производительностью

Это зависит. Я бы не удивился этому. Вы не упомянули, какой тип SSD вы используете. Современные твердотельные накопители Intel и Samsung довольно хорошо справляются с подобными операциями (чтение-изменение-запись) и будут работать лучше. Более дешевые / старые SSD (например, Corsair) будут медленными. Здесь определяющим фактором является количество операций ввода-вывода в секунду (IOPS).

ZFS является особенно медленно удалять вещи. Обычно удаление выполняется в фоновом режиме, поэтому вы не видите задержки. Если вы делаете огромное количество из них, он не может этого скрыть и должен задержать вас.


Приложение: почему удаление происходит медленно?

  • Удаление файла требует нескольких шагов. Метаданные файла должны быть помечены как «удаленные», и в конечном итоге они должны быть восстановлены, чтобы пространство можно было повторно использовать. ZFS - это «файловая система с журнальной структурой», которая работает лучше всего, если вы когда-либо создаете что-то, а не удаляете его. Структура журнала означает, что если вы что-то удалите, в журнале будет пробел, и поэтому другие данные необходимо переставить (дефрагментировать), чтобы заполнить пробел. Это незаметно для пользователя, но обычно выполняется медленно.
  • Изменения должны быть внесены таким образом, чтобы в случае сбоя питания на полпути файловая система оставалась согласованной. Часто это означает ожидание, пока диск не подтвердит, что данные действительно находятся на носителе; для SSD это может занять много времени (сотни миллисекунд). Чистый эффект от этого состоит в том, что требуется намного больше бухгалтерского учета (то есть операций ввода-вывода на диске).
  • Все изменения небольшие. Вместо того, чтобы читать, писать и стирать целые блоки флэш-памяти (или цилиндры для магнитного диска), вам нужно немного изменить один. Для этого аппаратное обеспечение должно считывать весь блок или цилиндр, изменять его в памяти, а затем снова записывать на носитель. На это уходит много времени.

Ян Хоусон дает хороший ответ на вопрос, почему он медленный.

Если вы удаляете файлы параллельно, вы можете увидеть увеличение скорости из-за того, что удаление может использовать одни и те же блоки и, таким образом, может сэкономить, перезаписывая один и тот же блок много раз.

Поэтому постарайтесь:

find /tmp -print0 | parallel -j100 -0 -n100 rm

и посмотрите, работает ли это лучше, чем ваши 70 удалений в секунду.

Как это возможно, что восстановление всего массива занимает час, а удаление с диска - 4 дня?

Это возможно, потому что эти две операции работают на разных уровнях стека файловой системы. Resilvering может выполняться на низком уровне и фактически не требует просмотра отдельных файлов, копируя большие фрагменты данных за раз.

Почему у меня такая плохая производительность? 70 удалений в секунду кажутся очень плохой производительностью.

Придется много бухгалтерии ...

Я мог бы удалить inode для / tmp2 вручную, но это не освободит место, верно?

Я не знаю, что касается ZFS, но если бы он мог автоматически восстановиться после этого, он, скорее всего, в конце концов, выполнял бы те же операции, которые вы уже выполняете, в фоновом режиме.

Может это проблема с zfs, жесткими дисками или чем-то еще?

Делает zfs scrub скажи что-нибудь?

Удаление большого количества файлов никогда не бывает быстрой операцией.

Чтобы удалить файл на любой файловой системы, вам необходимо прочитать индекс файла, удалить (или пометить как удаленный) запись файла в индексе, удалить любые другие метаданные, связанные с файлом, и пометить пространство, выделенное для файла, как неиспользуемое. Это нужно делать индивидуально для каждого удаляемого файла, а это означает, что для удаления большого количества файлов требуется множество мелких операций ввода-вывода. Чтобы сделать это способом, который обеспечивает целостность данных в случае сбоя питания, добавляет еще больше накладных расходов.

Даже без учета особенностей ZFS удаление 30 миллионов файлов обычно означает более ста миллионов отдельных операций ввода-вывода. это воля займет много времени даже с быстрым SSD. Как отмечали другие, дизайн ZFS еще больше усугубляет эту проблему.

Очень просто, если перевернуть мышление.

  1. Получите второй диск (похоже, он у вас уже есть)

  2. Скопируйте все с диска A на диск B с помощью rsync, за исключением каталога / tmp. Rsync будет медленнее, чем блочная копия.

  3. Перезагрузитесь, используя диск B в качестве нового загрузочного тома

  4. Переформатируйте диск A.

Это также приведет к дефрагментации вашего диска и предоставит вам новый каталог (хорошо, дефрагментация не так важна для SSD, но линеаризация ваших файлов никогда ничего не повредит)

У вас 30 миллионов записей в несортированном списке. Вы просматриваете список в поисках записи, которую хотите удалить, и удаляете ее. Теперь в вашем несортированном списке всего 29 999 999 записей. Если они все в / tmp, почему бы просто не перезагрузиться?


Отредактировано, чтобы отразить информацию в комментариях: Постановка проблемы: Удаление большинства, но не всеиз 30 млн. неправильно созданных файлов в / tmp занимает много времени.
Проблема 1) Лучший способ удалить большое количество ненужных файлов из / tmp.
Проблема 2) Понимание, почему файлы удаляются так медленно.

Решение 1) - большинство дистрибутивов * nix сбрасывают / tmp на пустой при загрузке. Однако FreeBSD не входит в их число.
Шаг 1 - скопируйте интересные файлы в другое место.
Шаг 2 - Как root

 $ grep -i tmp /etc/rc.conf  
 clear_tmp_enable="YES" # Clear /tmp at startup.  

Шаг 3 - перезагрузка.
Шаг 4 - снова измените clear_tmp_enable на «Нет».
Нежелательные файлы теперь удалены как ZFS на FreeBSD имеет особенность, заключающуюся в том, что «Уничтожение набора данных происходит намного быстрее, чем удаление всех файлов, которые находятся в наборе данных, поскольку при этом не требуется сканировать все файлы и обновлять все соответствующие метаданные». поэтому все, что ему нужно сделать во время загрузки, - это сбросить метаданные для набора данных / tmp. Это очень быстро.

Решение 2) Почему так медленно? ZFS - замечательная файловая система, которая включает в себя такие функции, как постоянный доступ к каталогам во времени. Это хорошо работает, если вы знаете, что делаете, но данные свидетельствуют о том, что OP не является экспертом по ZFS. OP не указал, как они пытались удалить файлы, но, предположительно, я бы сказал, что они использовали вариант «find regex -exec rm {} \;». Это хорошо работает с небольшими числами, но не масштабируется, потому что выполняются три последовательные операции: 1) получить список доступных файлов (возвращает 30 миллионов файлов в порядке хеширования), 2) использовать регулярное выражение для выбора следующего файла, который нужно удалить, 3 ) велите ОС найти и удалить этот файл из списка из 30 миллионов. Четный если ZFS возвращает список из памяти и если 'find' кеширует его, регулярное выражение по-прежнему должно идентифицировать следующий файл из списка, который будет обрабатываться, а затем указать ОС обновить свои метаданные, чтобы отразить это изменение, а затем обновить список, чтобы он больше не обрабатывался.