Какова философия задержки записи данных на диск?

72

В Linux завершенное выполнение команды, такой как cpили ddне означает, что данные были записаны на устройство. Например, необходимо вызвать syncили вызвать функцию «Безопасное извлечение» или «Извлечь» на диске.

Какая философия стоит за таким подходом? Почему данные не записываются сразу? Нет ли опасности, что запись не удастся из-за ошибки ввода-вывода?

marmistrz
источник
16
Помните, что системные вызовы чтения и записи могут работать с одним байтом за раз, но дисководы могут только читать или записывать блоки фиксированного размера. Затраты на байты за раз ввода / вывода были бы невыносимыми без буферизации. С буферизацией это терпимо.
Джонатан Леффлер

Ответы:

47

Какая философия стоит за таким подходом?

Эффективность (лучшее использование характеристик диска) и производительность (позволяет приложению продолжать работу сразу после записи).

Почему данные не записываются сразу?

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

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

Нет ли опасности, что запись не удастся из-за ошибки ввода-вывода?

Не обязательно. Это зависит от используемой файловой системы и имеющейся избыточности. Ошибка ввода-вывода может быть безвредной, если данные могут быть сохранены в другом месте. Современные файловые системы, такие как ZFS, самостоятельно исцеляют плохие блоки дисков. Также обратите внимание, что ошибки ввода-вывода не приводят к сбою современных ОС. Если они происходят во время доступа к данным, они просто сообщаются уязвимому приложению. Если они происходят во время доступа к структурным метаданным и подвергают файловую систему риску, она может быть перемонтирована только для чтения или недоступна.

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

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

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

jlliagre
источник
Помимо стоимости, подумайте, было ли сделано что-то, что зависит от сохраненных данных. Если я набираю текст в своем романе, сохраняя последовательно, и отключение питания означает, что я теряю 30 секунд работы, то, независимо от значения этих 30 секунд, по крайней мере, я возвращаюсь к состоянию, которое фактически имело место в процессе набора текста и я могу перезапустить оттуда. С другой стороны, если я нажму «сохранить», а затем вычеркну что-нибудь из моего списка дел на моем столе, то при восстановлении у меня будет несоответствие между моим жестким диском и бумагой. Как правило, это сложнее возобновить ...
Стив Джессоп
1
... так что, как обычный пользователь, я мог бы захотеть синхронизировать файловую систему перед тем, как вычеркнуть «закончить написание моего романа» из моего списка задач, чтобы убедиться, что я не думаю, что сделал что-то, что на самом деле дает сбой. И именно поэтому базы данных и тому подобное требуют синхронной записи: даже если они теряют данные, они обязательно должны поддерживать согласованность.
Стив Джессоп
1
@ SteveJessop Я согласен с вашим примером, но я не ожидаю, что случайный пользователь будет синхронизироваться вручную. Если редактор, используемый для написания драгоценного романа, не вызывает fsync или что-либо подобное при сохранении документа, это ошибка, которую необходимо исправить, например, bugs.launchpad.net/ubuntu/+source/libreoffice/+bug/817326 . Я бы использовал vi (vim) для написания моего, vim по умолчанию вызывает fsync при сохранении.
июля
59

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

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

Нет ли опасности, что запись не удастся из-за ошибки ввода-вывода?

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

frostschutz
источник
Некоторые контроллеры жестких дисков имеют резервный аккумулятор, поэтому в случае сбоя питания на контроллере сохраняются незафиксированные данные до тех пор, пока не будет восстановлено питание. Это позволяет использовать в приложениях базы данных, где потеря данных не вариант.
Страттонн
Linux хранит данные, еще не записанные в ОЗУ, а не на HDD. HDD тоже имеет свой кеш.
Барафу Альбино
Было бы очень удобно, если бы любой файл, открытый процессом, синхронизировался, когда процесс закрывался. Это не повлияет на сам процесс, но упростит сценарии оболочки и тому подобное (которые теперь должны синхронизировать целую файловую систему)
MSalters
14
Это больше, чем иллюзия. Асинхронные записи улучшают общую производительность приложений.
Jlliagre
4
@frostschutz: Помимо файлов, существующих только временно, существует также тот факт, что некоторые области файлов перезаписываются снова и снова.
Матье М.
26

Асинхронный буферизованный ввод / вывод использовался до Linux и даже до Unix. У Unix было это, и у всех его ответвлений.

Вот что написали Ричи и Томпсон в своей статье CACM «Система разделения времени UNIX» :

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


В своем вопросе вы также написали:

Нет ли опасности, что запись не удастся из-за ошибки ввода-вывода?

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

BSD добавил fsyncсистемный вызов, чтобы программа могла быть уверена, что ее файловые данные были полностью записаны на диск перед продолжением, и последующие системы Unix предоставили опции для синхронной записи. GNU dd имеет опцию, conv=fsyncчтобы убедиться, что все данные были записаны до выхода из команды. Это удобно при записи на медленные съемные флэш-накопители, где для записи буферизованных данных может потребоваться несколько минут.

Другим источником повреждения файлов является внезапное отключение системы, например, из-за потери питания. Практически все современные системы поддерживают флаг clean / dirty в своих файловых системах. Флаг устанавливается на очистку, когда больше нет данных для записи и файловая система собирается отключиться, как правило, во время завершения работы системы или путем ручного вызова umount. Системы обычно запускаются fsckпосле перезагрузки, если обнаружат, что файловые системы не были закрыты корректно.

Марк Плотник
источник
Предположим, мы копируем музыку с жесткого диска на внешний диск. Может случиться, что внешний диск поврежден и запись не удастся. Это не приведет к запуску программы с ошибочными данными. И кажется излишним паниковать из-за неудачного ввода-вывода на внешнем устройстве.
marmistrz
Хорошая точка зрения. Я изменю свой ответ.
Марк Плотник
15

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

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

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

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

Баард Копперуд
источник
2
XFS даже не решает, куда поместить данные до выписки. Задержка-распределение дает распределителю гораздо больше информации для принятия решений. Когда файл впервые записывается, нет способа узнать, будет ли это файл 4k или файл 1G и все еще растущий. Если где-то есть 10G смежного свободного места, поместить файл 4k в начало не имеет смысла. Размещение большого файла в начале большого свободного пространства уменьшает фрагментацию.
Питер Кордес
13

Он не специфичен для Linux и называется кешем страниц (что у Linux довольно хорошо). Смотрите также http://linuxatemyram.com/ ; поэтому, если файл записан, то через несколько секунд прочитайте снова, очень часто не требуется дисковый ввод-вывод.

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

Код приложения может дать подсказки относительно этого кэширования: см., Например, posix_fadvise (2) и madvise (2)

Василий Старынкевич
источник
8

Вращающиеся пластины работают медленнее, чем RAM. Мы используем кэширование операций чтения / записи, чтобы «скрыть» этот факт.

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

Таким образом, записи выполняются в мягких временных рамках - пока наша поддерживаемая пропускная способность не превышает пропускную способность нашего диска, мы можем скрыть много потерь производительности в кэше записи.

И нам нужно писать в кеш - вращающиеся диски сравнительно медленные. Но так что современные типы RAID имеют существенные неудобства для работы.

Например, RAID 6, чтобы выполнить один ввод-вывод, должен:

  • Читать блок обновления
  • читать паритет1
  • читать паритет 2
  • написать новый блок
  • написать паритет 1
  • написать четность 2

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

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

Это очень желательно сделать, потому что тогда у вас больше не будет усиления записи. В самом деле, вы можете получить более низкий штраф за запись, чем RAID 1 + 0.

Рассмотреть возможность:

RAID 6, 8 + 2 - 10 шпинделей.

8 последовательных блоков данных для записи - вычислить четность в кеше и записать один блок на каждый диск. 10 записей на 8 означает штраф за запись 1,25. 10 дисков RAID 1 + 0 по-прежнему имеют штраф на запись 2 (потому что вы должны записывать в каждое подзеркало). Таким образом, в этом сценарии вы можете заставить RAID 6 работать лучше, чем RAID1 + 0. В реальном мире вы получаете немного больше смешанного профиля ввода-вывода.

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

А если нет, то вы страдаете от медленной производительности SATA, но умножаете ее на 6 и добавляете некоторую конкуренцию. Ваш 10-канальный SATA RAID-6 без кэширования записи будет немного быстрее, чем один диск без RAID ... но не намного.

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

Sobrique
источник
7

Ни в одном из других ответов не упоминается задержка распределения . XFS, ext4, BTRFS и ZFS все используют его. XFS использует его еще до появления ext4, поэтому я буду использовать его в качестве примера:

XFS даже не решает, куда поместить данные до выписки. Задержка-распределение дает распределителю гораздо больше информации для принятия решений. Когда файл впервые записывается, нет способа узнать, будет ли это файл 4k или файл 1G и все еще растущий. Если где-то есть 10G смежного свободного места, поместить файл 4k в начало не имеет смысла. Размещение большого файла в начале большого свободного пространства уменьшает фрагментацию.

Питер Кордес
источник
4

Все остальные ответы здесь, как минимум, в основном правильны для обычного случая, и я бы рекомендовал прочитать любой из них перед моим, но вы упомянули, что dd и dd имеют типичный вариант использования, который может не включать кэширование записи. Кэширование записи в основном реализовано на уровне файловой системы. Необработанные устройства обычно не выполняют кэширование при записи (различные драйверы устройств, такие как raid или lvm, являются еще одним шариком воска). Поскольку dd часто используется с необработанными блочными устройствами, он предоставляет параметры bs и связанные с ними параметры, позволяющие выполнять большие записи для повышения производительности на необработанных устройствах. Это не так полезно, когда обе конечные точки являются обычными файлами (хотя при больших операциях записи в этом случае используется меньше системных вызовов). Другое распространенное место, где это особенно заметно, - это пакет mtools, являющийся реализацией файловой системы в пользовательском пространстве. использование mtools с флоппи-дисководом всегда кажется невероятно медленным, поскольку инструменты полностью синхронизированы, а флоппи-дисководы невероятно медленны. Монтирование дискеты и использование файловой системы с толстым ядром намного более отзывчивы, за исключением размонтирования, которое является синхронным (и очень важно, чтобы он предотвращал потерю данных, особенно для съемных устройств, таких как дискеты). Есть только несколько других программ, которые, как мне известно, регулярно используются с необработанными устройствами, такими как специально настроенные базы данных (которые реализуют их собственное кэширование записи), tar и специальные инструменты для устройств и файловых систем, такие как chdsk, mkfs и mt. Монтирование дискеты и использование файловой системы с толстым ядром намного более отзывчивы, за исключением размонтирования, которое является синхронным (и очень важно, чтобы он предотвращал потерю данных, особенно для съемных устройств, таких как дискеты). Есть только несколько других программ, которые, как мне известно, регулярно используются с необработанными устройствами, такими как специально настроенные базы данных (которые реализуют их собственное кэширование записи), tar и специальные инструменты для устройств и файловых систем, такие как chdsk, mkfs и mt. Монтирование дискеты и использование файловой системы с толстым ядром намного более отзывчивы, за исключением размонтирования, которое является синхронным (и очень важно, чтобы он предотвращал потерю данных, особенно для съемных устройств, таких как дискеты). Есть только несколько других программ, которые, как мне известно, регулярно используются с необработанными устройствами, такими как специально настроенные базы данных (которые реализуют их собственное кэширование записи), tar и специальные инструменты для устройств и файловых систем, такие как chdsk, mkfs и mt.

hildred
источник
4
Блочные устройства Linux по умолчанию читают / записывают кеш страниц. Вы должны использовать, O_DIRECTесли вы хотите обойти кеш. dd oflag=direct, IIRC, некоторые устройства по умолчанию направляют ввод / вывод на блочных устройствах. (И требуют чтения / записи выровненных блоков, чего нет в Linux, потому что в любом случае это просто запись кэша страниц.)
Питер Кордес
3

Философия небезопасна по умолчанию.

Возможны две разумные и очевидные стратегии: немедленная запись на диск или задержка записи. UNIX исторически выбрал последнее. Так что получите безопасность, вам нужно позвонить fsyncпотом.

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

Помните, что UNIX был разработан для компьютерных экспертов. «Безопасный по умолчанию» не рассматривался. Безопасность означает более медленный ввод-вывод, и эти ранние системы действительно имели медленный ввод-вывод, что делает цену более высокой. К сожалению, ни UNIX, ни Linux не переключились на safe-be-default, хотя это и является непреложным изменением.

MSalters
источник
6
Подавляющее большинство приложений и пользователей не нуждаются или не заботятся о безопасности, которую обеспечит синхронная запись. В случае сбоя или отключения электроэнергии вы рискуете потерять данные за последние 30 секунд. Это нормально для большинства людей, за исключением случаев, когда речь идет о финансовой транзакции или чем-то подобном, которая будет стоить более 30 секунд нашего времени. По умолчанию синхронные операции ввода-вывода подразумевали бы, что все приложения, для которых предназначено удобство использования, должны определять O_NOSYNC.
Jlliagre
2

Он обменивает небольшую надежность на значительное увеличение пропускной способности.

Предположим, например, программа сжатия видео. С отложенной записью («обратная запись»):

  1. потратить 10мс на сжатие кадра
  2. выдать запись кадра на диск
  3. подождите 10 мсек, пока диск подтвердит, что запись завершена
  4. GOTO 1

Против

  1. потратить 10мс на сжатие кадра
  2. выдать запись кадра на диск (завершается в фоновом режиме)
  3. GOTO 1

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

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

pjc50
источник
1

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

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

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

  3. Приложение специально запрашивает подтверждение того, что запись фактически завершена.

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

Supercat
источник
0

Существует также это:

Напишите «Привет, Джо Мо»
быстрее, чем:
Напишите «Привет»,
напишите «Джо»
Напишите «Мо»

А также:

Напиши "Привет, как дела?"
быстрее чем:
напиши "Привет, как дела?"
Удалить это
Написать "Привет, как дела?"
Удалить это
Написать "Привет, как дела?"

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

Рольф
источник