Как реализовать атомарное обновление 2 файлов?



@AshBlade

Пишу приложение на .NET, которое хранит свои данные в файлах и обновление состояния происходит с помощью алгоритма Raft.
Есть 2 файла: снапшот и лог команд. При сохранении нового снапшота необходимо
1. Заменить содержимое старого снапшота, и
2. Обновить лог соответствующим образом (очистить до нужной команды).

Вопрос: как реализовать атомарное обновление этих 2 файлов, чтобы в случае сбоя смог откатиться к корректному состоянию?

На данный момент, в голову пришла такая идея:
1. Создаем временные файлы снапшота и лога и сохраняем в них новое состояние
2. Делаем запись в UNDO логе о том, что необходимо выполнить перемещение этих 2 файлов на место старых файлов снапшота и лога. Т.е. выполнить mv / File.Move
3. Выполняем перемещение
4. Коммитим изменения в UNDO логе (чтобы больше не выполняли операции)

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


Решения вопроса 2



@mvv-rus

Движок ESE от Microsoft (его используют системные БД MS Windows и MS Exchange) на для уменьшения объема просматриваемого журнала транзакций («лога», он там хранится не в одном большом файле а в куче мелких) при рестарте создает и обновляет отдельный файл контрольной точки, в котором сохраняется ссылка на транзакцию, до которой все точно зафиксировано. А при рестарте — запускает применение журнала транзакций с контрольной точки.
Попробуйте подумать в эту сторону — может, подойдет.
PS А еще в Windows, в файловой системе NTFS есть встроенная поддержка транзакционного обновления. Но, во-первых — это только в Windows, а во-вторых, я не помню, чтобы в .NET была библиотека для использования этой возможности, так что, не исключено, что доступаться до нее придется через P/Invoke


Ответы на вопрос 1



@mindtester

у тебя ключевое слово — транзакция. медитируй над ним.

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

… я так думаю… раз уж ты не на бд, а на файлы оперся…

ps ну или временный лог транзакции… так сказать.. ну и все чистить по успешному завершению

pps MVV,

в файловой системе NTFS есть встроенная поддержка транзакционного обновления

еще бы нарыть инфу об этом )))
— это белее чем реалистично, современные ФС (а NTFS точно) по сути специализированные СУБД
— подписываюсь!
— если кто нароет хотя бы на уровне winapi, подписываюсь допилить до шарпа.. ну мало ли… ну или поделитесь!!! )))

… хотя на отдельных файлах флагах-этапов транзакции.. скорее топорно, но надежно… по тому что топорно ;)))
… а еще и переносимо между ОС ))

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *