Я написал программу с ошибками, которая случайно создала около 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 является особенно медленно удалять вещи. Обычно удаление выполняется в фоновом режиме, поэтому вы не видите задержки. Если вы делаете огромное количество из них, он не может этого скрыть и должен задержать вас.
Приложение: почему удаление происходит медленно?
Ян Хоусон дает хороший ответ на вопрос, почему он медленный.
Если вы удаляете файлы параллельно, вы можете увидеть увеличение скорости из-за того, что удаление может использовать одни и те же блоки и, таким образом, может сэкономить, перезаписывая один и тот же блок много раз.
Поэтому постарайтесь:
find /tmp -print0 | parallel -j100 -0 -n100 rm
и посмотрите, работает ли это лучше, чем ваши 70 удалений в секунду.
Как это возможно, что восстановление всего массива занимает час, а удаление с диска - 4 дня?
Это возможно, потому что эти две операции работают на разных уровнях стека файловой системы. Resilvering может выполняться на низком уровне и фактически не требует просмотра отдельных файлов, копируя большие фрагменты данных за раз.
Почему у меня такая плохая производительность? 70 удалений в секунду кажутся очень плохой производительностью.
Придется много бухгалтерии ...
Я мог бы удалить inode для / tmp2 вручную, но это не освободит место, верно?
Я не знаю, что касается ZFS, но если бы он мог автоматически восстановиться после этого, он, скорее всего, в конце концов, выполнял бы те же операции, которые вы уже выполняете, в фоновом режиме.
Может это проблема с zfs, жесткими дисками или чем-то еще?
Делает zfs scrub
скажи что-нибудь?
Удаление большого количества файлов никогда не бывает быстрой операцией.
Чтобы удалить файл на любой файловой системы, вам необходимо прочитать индекс файла, удалить (или пометить как удаленный) запись файла в индексе, удалить любые другие метаданные, связанные с файлом, и пометить пространство, выделенное для файла, как неиспользуемое. Это нужно делать индивидуально для каждого удаляемого файла, а это означает, что для удаления большого количества файлов требуется множество мелких операций ввода-вывода. Чтобы сделать это способом, который обеспечивает целостность данных в случае сбоя питания, добавляет еще больше накладных расходов.
Даже без учета особенностей ZFS удаление 30 миллионов файлов обычно означает более ста миллионов отдельных операций ввода-вывода. это воля займет много времени даже с быстрым SSD. Как отмечали другие, дизайн ZFS еще больше усугубляет эту проблему.
Очень просто, если перевернуть мышление.
Получите второй диск (похоже, он у вас уже есть)
Скопируйте все с диска A на диск B с помощью rsync, за исключением каталога / tmp. Rsync будет медленнее, чем блочная копия.
Перезагрузитесь, используя диск B в качестве нового загрузочного тома
Переформатируйте диск 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' кеширует его, регулярное выражение по-прежнему должно идентифицировать следующий файл из списка, который будет обрабатываться, а затем указать ОС обновить свои метаданные, чтобы отразить это изменение, а затем обновить список, чтобы он больше не обрабатывался.