Реализация атомарной записи в файл в нетранзакционной файловой системе - PullRequest
3 голосов
/ 01 февраля 2012

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

Я сделал следующие предположения:

  • Используемая файловая система поддерживает атомарные операции на уровне inode (например, NTFS).Это означает, что move и delete являются атомарными.
  • Доступ к файлам имеет только сама программа.
  • В программе имеется только 1 экземпляр программы.время, и он действует однопоточным образом.
  • Для простоты каждый раз записывается содержимое всего файла (т. е. усеченная запись).

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

Я предлагаю следующий процесс:

  1. Запись новогосодержимое во временный файл Новый
  2. Перемещение исходного файла Оригинал во временное расположение Резервное копирование
  3. Перемещение Новый до Оригинал
  4. Удалить Резервное копирование

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

Это, однако, еще не делает операцию атомарной.Процесс может быть прерван шагами 1, 2, 3 или 4:

  1. Оставляет потенциально незавершенным Новый .
  2. Перемещение является атомарным, но целевой файлсейчас отсутствует.Обе Новые и Резервная копия существуют и завершены.
  3. Перемещение является атомарным, но есть неиспользованная Резервная копия . Оригинал был заменен на Новый контент
  4. Удаление является атомарным.

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

  • Если Новый существует, но Резервная копия нет, мы потерпели крах в или после шага 1. Удалить Новый , поскольку он может быть неполным.
  • Если существует Новый и существует Резервная копия , мы потерпели крах после шага 2. Перейдите к шагу 3.
  • Если Резервное копирование существует, но Новое тоже не произошло, то мы потерпели крах после шага 3. Продолжите с шага 4.

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

Я считаю, что эта идея обеспечивает атомарную запись для одной программы.Эти проблемы все еще существуют:

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

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

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

Ответы [ 2 ]

4 голосов
/ 01 февраля 2012

Есть только одна вещь, которую вы должны принять, переименование файла - атомарная операция

Таким образом, следующие шаги обеспечат исправление (по крайней мере, в Unix, например, в ОС)

  1. Запись нового содержимого во временный файл. New
  2. переименовать временный файл в оригинальное имя

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

3 голосов
/ 01 февраля 2012

Ваши шаги могут быть еще более упрощены:

  1. Запись нового содержимого во временный файл New
  2. Удаление исходного файла
  3. Перемещение нового в оригинал

При запуске:

  1. Если Оригинал не существует, но Новый существует, процесс был прерван до шага 3, переместите Новый в Оригинал.
  2. Если Оригинал и Новый обасуществует, процесс был прерван до шага 2, удалите New.

Я использовал это при управлении файлами конфигурации и никогда не сталкивался с проблемой этого процесса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...