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

Почему dd не отвечает на запросы?

Как root я вчера сделал

dd if=/dev/zero of=/var/lib/libvirt/images/dat.img bs=1G count=1000

и в течение многих часов сервер полностью не отвечал.

Контроллер рейда - HP P410 с 4 дисками в рейде 1 + 0.

Это проблема, которую я использовал bs=1G или, может быть, CentOS нужен параметр ядра, поэтому тяжелый ввод-вывод не может остановить хост?

Вопрос

Кто-нибудь может объяснить, почему это происходит?

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

Короткий ответ: сервер перестает отвечать, потому что вы заполнили почти всю память грязными страницами (то есть: данные, которые должны быть удалены).

Длинный ответ: как правило, операции записи не передают данные на резервное устройство немедленно. Скорее они кэшируются в кэше страниц. Это сделано из соображений производительности: хранилище (особенно жесткие диски) довольно медленное по сравнению с ЦП / памятью, поэтому кэширование в максимально возможной степени значительно увеличивает скорость ввода-вывода. Однако, если вы вообще пишете слишком много, кэш страниц будет лихорадочно (и с высоким приоритетом) сбрасывать на диски как можно больше данных. Это заставляет вызывающий процесс перейти в "глубокий сон" - это означает, что вы не можете его прервать, потому что, ну, это не действительно работает, скорее сам ждет, когда его разбудит ядро. Более того, поскольку очистка грязных данных является дорогостоящей и высокоприоритетной операцией, весь сервер становится очень медленным.

Тем не менее, как вы можете создавать большие файлы изображений, не сокращая сервер до обхода? У вас были разные варианты:

  • запустите свой dd команда, добавляющая oflag=direct вариант: это вызовет dd к обходить кеш страницы, напрямую записывая на диски. Я также предлагаю использовать буфер меньшего размера, например: 1 МБ, используя что-то подобное dd if=/dev/zero of=/var/lib/libvirt/images/dat.img bs=1M count=1000000. Обратите внимание, что эта команда выше воля несколько замедлить сервер во время выполнения (все-таки вы пишете на диски), но и рядом с вами первой попытки;
  • лучший подход для создания полностью выделенного файла - использовать fallocate команда, то есть: fallocate /var/lib/libvirt/images/dat.img -l 1G. При выделении с помощью обработки метаданных и без записи реальных данных эта команда вернется почти сразу, не вызывая замедления. Многие современные файловые системы поддерживают его, за исключением ZFS;
  • наконец, вы можете использовать разреженный файл - файл с номинальным размером, но без реального размещения. Вы можете создать его, выполнив truncate --size=1G /var/lib/libvirt/images/dat.img. Эта команда вернется немедленно, практически не вызывая операций ввода-вывода.

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

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

Итак, разумно использовать, например, bs=16M для вашей задачи. Это достаточно приличный размер буфера, чтобы обеспечить эффективный ввод-вывод, при этом он достаточно детализирован, чтобы ничего не связывать слишком сильно.