Как я могу синхронизировать два процесса, обращающихся к файлу на NAS?

Вот в чем дело: у меня есть два приложения, написанных на C++ и работающих на двух машинах с разными ОС (одна Linux и одна Windows). Один из этих процессов отвечает за обновление файла XML на NAS (сетевое хранилище), а другой читает этот файл.

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


person Luc Touraille    schedule 23.01.2009    source источник


Ответы (5)


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

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

Читатель: Проверить файл блокировки записи, создать файл блокировки чтения, проверить файл блокировки записи, если существует, удалить файл чтения и прервать.

Writer: Проверить файл блокировки чтения, создать файл блокировки записи, проверить файл блокировки чтения, если он существует, удалить файл блокировки записи и прервать.

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

person Wolfwyrd    schedule 23.01.2009
comment
Ну, это простое решение, которое мы использовали, но как вы можете гарантировать, что оба процесса не будут проверять наличие файла одновременно, а затем успешно заблокируются и начнут запись/чтение вместе? - person Luc Touraille; 23.01.2009
comment
Блокировка с двойной проверкой, блокировка файла для чтения и записи, проверка отсутствия файла, создание файла, проверка отсутствия файла, а затем выполнение следующих действий: en.wikipedia.org/wiki/Double-checked_locking - person Wolfwyrd; 23.01.2009
comment
@Волфвид. Нет. Для этого в файловые системы *nix уже встроена функциональность: выполните 'man 2 flock()'. Обеспечивает рекомендательные блокировки файлов как в общем, так и в монопольном режиме. - person Martin York; 23.01.2009

Спасибо всем за ваши ответы.

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

person Luc Touraille    schedule 26.01.2009

Хорошо, вам нужен какой-то механизм блокировки для контроля доступа.

Большинство файловых систем *nix обеспечивают это. Я подозреваю, что он также доступен в файловой системе Windows (поскольку этот механизм используется perl), но у него может быть другое имя.

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

flock() предоставляет как общие блокировки (или блокировку READ), так и эксклюзивные блокировки (или блокировку WRITE). flock будет блокировать ваш поток (не занятым способом) до тех пор, пока файл не будет разблокирован пользователем (он также обеспечивает НЕБЛОКИРУЮЩИЕ проверки, чтобы вы могли заниматься другими делами во время ожидания).

Проверьте flock в разделе 2 справочных страниц.

int     flock(int fd, int operation);

Flock() applies or removes an advisory lock on the file associated with the file
descriptor fd.  A lock is applied by specifying an operation parameter that is
one of LOCK_SH or LOCK_EX with the optional addition of LOCK_NB.  To unlock an
existing lock operation should be LOCK_UN.
person Martin York    schedule 23.01.2009
comment
Не гарантируется, что flock будет вести себя ожидаемым образом на общих ресурсах NFS со старыми версиями Linux. - person David Holm; 23.01.2009

Если файлы находятся в общей папке NFS, вы можете использовать fcntl(2) для блокировки файл. Проверьте вопрос D10 в Часто задаваемые вопросы по Linux NFS. У меня очень мало опыта работы с Windows API, но, насколько я слышал, они имеют хорошую поддержку POSIX, поэтому вы сможете использовать fcntl, если они поддерживают POSIX.1-2001.

Если вы получаете доступ к файлам, используя разные протоколы (например, AFS или SMB), возможно, вы могли бы настроить простой сервер синхронизации, который управляет блокировками через интерфейс IPC?

person David Holm    schedule 23.01.2009

Можно ли переключиться с файлов на базу данных?

Этот тип параллелизма — это то, с чем СУБД справляются очень хорошо. Он не должен быть дорогим или сложным в установке. MySql, Postgress или JavaDB прекрасно справятся с этим практически бесплатно.

В случае неудачи с параметром базы данных я бы попросил процесс записи записать в «скрытое» имя файла, например «.updateinprogress.xml», и переименовать файл после завершения обновления. В большинстве систем "mv" или "ren" являются атомарными операциями, поэтому процесс чтения выбирает либо старый файл, либо новый файл, но никогда не записанный наполовину.

person James Anderson    schedule 23.01.2009