Файловое хранилище для файлов с одновременным доступом
От: corpse56  
Дата: 25.01.22 22:14
Оценка:
Здравствуйте!
Задача не новая, но я не соображу как правильно поискать по теме. Опишу своими словами.

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

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

Удалось сообразить два сценария, которые могут это предотвратить:

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

2. При скачивании файла, вычисляем его хэш, а когда пытаемся загрузить изменённый файл, то проверяем хэш. Если хэш изменился, значит даём отлуп и просим скачать файл заново. Это вроде как оптимистическая блокировка.

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

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

Спасибо!

пс
использую .NET C#

извините за сумбур.
Re: Файловое хранилище для файлов с одновременным доступом
От: reversecode google
Дата: 25.01.22 22:25
Оценка:
git svn cvs итд уже давно придумали
но вы можете изобрести их вновь
Re: Файловое хранилище для файлов с одновременным доступом
От: L.K. Марс  
Дата: 25.01.22 23:03
Оценка: 1 (1) +1
C>Всё прекрасно

Если всё прекрасно, тогда оставляем всё как есть и занимаемся другими, более насущными делами.

Ну и хранить файлы в базе... зачем?
Re: Файловое хранилище для файлов с одновременным доступом
От: vmpire Россия  
Дата: 25.01.22 23:04
Оценка: 2 (1) +2
Здравствуйте, corpse56, Вы писали:

C>Теперь правила меняются. Файл должен хранится в базе. Запихнуть существующие файлы в базу и организовать их получение и загрузку не трудно. У меня возникают вопросы по поводу совместного доступа к одному и тому же файлу.

...
C>Система эта не высоконагруженная. Около 50 пользователей. Конечно, случай конкурентного доступа маловероятен. Но тем не менее, хотелось бы узнать как решать такую задачу?
Собственно, Вы уже и описали два основных способа реализации подобных задач: оптимистическая или пессимистическая блокировки.
Так их и решают.

Другое дело, что в данном случае проблема создаётся искуственно. А с точки зрения базы редактирование отдельных частей документа — это в чистом виде нарушение первой нормальной формы, со всеми вытекающими проблемами.
Более хорошее решение в общем виде придумать сложно.
Если у файлов есть какая-то специфика (например, это xml файлы, которые редактируются по частям), то можно распилить их по отдельным полям базы.
Если это файлы MS Office, то разумно их переложить, например, на sharepoint и обновлять в базе оттуда (как именно — вопрос технический и не очень сложный). Sharepoint сам разберётся с совместным использованием, и даже позволит совместно редактировать онлайн.
Если вообще без вариантов, вынь да полож именно базу, то единственное, что можно предложить, это добавить к оптимистической модели предупреждение пользователям, если двое одновременно открыли запись с файлом (предупреждать обоих). Это немного снизит остроту проблемы.
Re[2]: Файловое хранилище для файлов с одновременным доступом
От: vmpire Россия  
Дата: 25.01.22 23:05
Оценка:
Здравствуйте, reversecode, Вы писали:

R>git svn cvs итд уже давно придумали

R>но вы можете изобрести их вновь
Там те же самые оптимистическая либо пессимистическая модели. VCS тут проблему не решат.
Re[2]: Файловое хранилище для файлов с одновременным доступом
От: corpse56  
Дата: 25.01.22 23:16
Оценка:
Здравствуйте, reversecode, Вы писали:

R>git svn cvs итд уже давно придумали

R>но вы можете изобрести их вновь

Спасибо за ответ!

Поясните, пожалуйста, как системы контроля версий применить в данном случае?
Ведь не заставишь же обычных пользователей изучать гит. Получается, что вы предлагаете следующую схему:
1. Поднимаем свой гит-сервер.
2. Храним все файлы там.
3. Клиентское приложение коммитит туда изменения файла.

Правильно ли я вас понял?

Забыл уточнить, что файлы в основном офисные. pdf, autocad, solid, excel, word и т.п.



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

я не очень в этом силён, но не хотелось бы нагружать пользователей дополнительной работой и объяснениями принципов работы гит.
Re: Файловое хранилище для файлов с одновременным доступом
От: samius Япония http://sams-tricks.blogspot.com
Дата: 26.01.22 01:40
Оценка: 1 (1)
Здравствуйте, corpse56, Вы писали:

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


C>Теперь правила меняются. Файл должен хранится в базе.

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

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


C>В первом сценарии пользователи будут негодовать, что не могут загрузить мелкие изменения в файле (а потом и вовсе забыть, что что-то менял), во время того, как один из пользователей работает с файлом целый день, во втором сценарии пользователи будут ворчать от того, что изменения, которые они проделали в файле, нужно будет заново вносить в новую версию файла, при чём теоретически это может произойти подряд несколько раз.


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

Хочу сразу предупредить, MSOffice при работе с файлами использует несколько подходов. Основной — сохранение нового контента во временный файл с последующей подменой оригинала. Такой трюк может использоваться до несколких раз при единичном сохранении. Есть еще legacy режим, когда файл изменяется по-месту через открытие на запись. Этот подход используется для обновления списка пользователей, которые этот файл редактируют в данный момент. Оба подхода могут быть применены к одному файлу. Подмена — для сохранения новых версий, прямое изменение — для удаления записи о редактирующем пользователе. Доставка содержимого файла в базу должна учитывать эти моменты.
Re: Файловое хранилище для файлов с одновременным доступом
От: Sinclair Россия https://github.com/evilguest/
Дата: 26.01.22 05:04
Оценка: 11 (2) +1
Здравствуйте, corpse56, Вы писали:

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

За последние 20 лет к описанным вами двум подходам (первый, кстати, называется персистентные блокировки) (см. тж. https://rsdn.org/forum/db/121769
Автор: Sinclair
Дата: 28.10.02
) добавился более современный подход на основе CRDT и совместного редактирования.
Тот же офис умеет при размещении файлов в OneDrive давать редактировать их совместно, в стиле, похожем на Google Docs.

Точнее, это две разные фичи:
1. CRDT — это фактически "автомёрдж", который умеет сливать два произвольных набора изменений независимо от их порядка.
К сожалению, при большом объёме параллельных изменений результат этого авто-мёрджа может оказаться весьма неинтуитивным.
2. Совместное редактирование приходит на помощь: вместо того, чтобы пытаться слить воедино две правки, каждая из которых изменила 80% документа, происходит постоянное объединение микро-правок. Так что версии редко разъезжаются далеко друг от друга.

А вам нужно прежде всего определиться с требованиями. Стандартный бюрократический документооборот подразумевает "пошаговую стратегию", где стороны обмениваются правками, вносимыми по очереди.
При движении по этому пути вам нужно понять — есть ли способ определить "на чьей стороне мячик". Если есть — то велком в чекаут/чекин и персистентные блокировки. Если нету (пользователь хочет иметь возможность начать правки внезапно, независимо от возможности захватить блокировку), то придётся готовиться к разрешению конфликтов. Способы их задетектировать вы описали правильно — либо version tag, либо хеш. Ну, а дальше — делаем merge либо вручную, либо автоматом.

Если же требования позволяют применить совместное редактирование — можно попробовать применить его. Из коробки оно работает с SharePoint (файлы как раз будут лежать в базе данных ).
Наверное, можно эмулировать SharePoint Server для офиса. Когда я смотрел на него в прошлый раз (а это было давно, ещё до collaboration), там под капотом был просто WebDAV протокол. Скорее всего, они его чем-то расширили.
Подробности должны быть где-то здесь: https://docs.microsoft.com/en-us/openspecs/office_protocols/ms-ocproto/f851881e-6c7f-4546-a009-7bd905485f9d
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: Файловое хранилище для файлов с одновременным доступом
От: Vasiliy2  
Дата: 26.01.22 06:12
Оценка: 3 (2)
Здравствуйте, corpse56, Вы писали:



C>Забыл уточнить, что файлы в основном офисные. pdf, autocad, solid, excel, word и т.п.


C>Но тогда возникает проблема с множеством версий. Это усложняет жизнь пользователям. Например, два пользователя дополняют одну и ту же принципиальную электрическую схему (таблицу, документ). Третьему пользователя, тому, кто захочет этой схемой воспользоваться на производстве, придётся как-то хитро извлекать работу этих двух пользователей. Хотя гит же перед тем как пушить, если что-то изменено, просит запулить изменения... начинаю запутываться. Не пойму как это организовать.


C>я не очень в этом силён, но не хотелось бы нагружать пользователей дополнительной работой и объяснениями принципов работы гит.


На производстве — только персистентные блокировки и, как сказали уже сказали в другой ветке — чекин/чекаут. Иначе у вас потом из модели в железе будет полная ерунда, а не то, что ожидалось, один поменял, второй поменял, а на изготовление ушло что-то среднее. Причем стоит хранить все версии, чтобы понять, что поменялось. Это стандартный подход PDM систем. Хранить файлы можно либо в базе, если их не много (если много, то в конце концов база данных будет пухнуть не от значимых данных, а от простых бинарников), либо использовать какое нибудь хранлище, например локальный S3 (для него есть много реализаций).

Если вы пишите свою PDM, то делайте состояния у файлов/документов, чтобы понять какая версия на данный момент актуальная. Тогда не будет сложностей с пониманием этой проблемы. Если у вас ~50 клиентов будет, то просто показывайте, кто взял в работу файл, пользователи сами при необходимости созвонятся и договорятся, о том, кто и когда освободит файл.
Re[2]: Файловое хранилище для файлов с одновременным доступом
От: Sharov Россия  
Дата: 26.01.22 08:10
Оценка:
Здравствуйте, vmpire, Вы писали:

V>Другое дело, что в данном случае проблема создаётся искуственно. А с точки зрения базы редактирование отдельных частей документа — это в чистом виде нарушение первой нормальной формы, со всеми вытекающими проблемами.


Почему нарушение 1нф? Мн-во обычных update'ов
Кодом людям нужно помогать!
Re: Файловое хранилище для файлов с одновременным доступом
От: vsb Казахстан  
Дата: 26.01.22 08:34
Оценка: 2 (1)
Здравствуйте, corpse56, Вы писали:

C>Теперь правила меняются. Файл должен хранится в базе. Запихнуть существующие файлы в базу и организовать их получение и загрузку не трудно. У меня возникают вопросы по поводу совместного доступа к одному и тому же файлу.

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

А сейчас как пользователи справляются с этим?

C>1. Если файл необходимо отредактировать (то есть скачать к себе, изменить и загрузить изменённый), пользователь запускает режим редактирования, при котором все остальные пользователи не могут загружать изменённый файл до тех пор, пока пользователь сам не закроет режим редактирования либо истечёт время, отведённое на блокировку. То есть все ждут, пока пользователь не закончит режим редактирования. Это похоже на пессимистическую блокировку, если я правильно понимаю.


C>2. При скачивании файла, вычисляем его хэш, а когда пытаемся загрузить изменённый файл, то проверяем хэш. Если хэш изменился, значит даём отлуп и просим скачать файл заново. Это вроде как оптимистическая блокировка.


Всё верно.

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


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

PS в базе файлы хранить это плохая идея. Храните лучше в облаке.
Отредактировано 26.01.2022 8:35 vsb . Предыдущая версия .
Re: Файловое хранилище для файлов с одновременным доступом
От: wildwind Россия  
Дата: 26.01.22 09:43
Оценка: 3 (1)
Здравствуйте, corpse56, Вы писали:

C>Например два пользователя хотят редактировать один и тот же файл.


Если бизнес процесс предусматривает одновременное редактирование файла несколькими пользователями, почему эта информация хранится в файле, а не в базе, в нормализованном виде?

Тут либо бизнес-процесс кривой, либо архитектура.
Re[3]: Файловое хранилище для файлов с одновременным доступом
От: vmpire Россия  
Дата: 26.01.22 10:14
Оценка: 6 (2)
Здравствуйте, Sharov, Вы писали:

S>Почему нарушение 1нф? Мн-во обычных update'ов

Если в базе приходится делать операции по изменению части данных какого-то поля, то поле уже нельзя рассматривать, как атоммарное.
Re[2]: Файловое хранилище для файлов с одновременным доступом
От: Джеффри  
Дата: 26.01.22 10:53
Оценка: 5 (2)
Здравствуйте, wildwind, Вы писали:

W>Если бизнес процесс предусматривает одновременное редактирование файла несколькими пользователями, почему эта информация хранится в файле, а не в базе, в нормализованном виде?


Это проблема полностью не уйдет даже, если нормализовать данные. Просто представьте, что у вас есть таблица и два пользователя параллельно работают с одной записью. То, что описал ТС, это классическая диллема между оптимистической и пессимистической блокировкой.
Re[4]: Файловое хранилище для файлов с одновременным доступом
От: Sharov Россия  
Дата: 26.01.22 11:17
Оценка:
Здравствуйте, vmpire, Вы писали:

S>>Почему нарушение 1нф? Мн-во обычных update'ов

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

А почему файл нельзя представить себе как бинарь, т.е. большая строка 0\1 (так он и хранится), а его изменения как update(измененнный бинарь)?
И так для всех операций. Т.е. мы меняем объект целиком, а не частями.
Кодом людям нужно помогать!
Re[3]: Файловое хранилище для файлов с одновременным доступом
От: wildwind Россия  
Дата: 26.01.22 11:30
Оценка: 3 (1)
Здравствуйте, Джеффри, Вы писали:

Д>Это проблема полностью не уйдет даже, если нормализовать данные.


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

Д>Просто представьте, что у вас есть таблица и два пользователя параллельно работают с одной записью.


Даже если так (что бывает редко), то, как ты верно заметил, это хорошо известная проблема. И самые эффективные методы ее решения реализованы именно в СУБД, а не в офисных пакетах.
Re: Файловое хранилище для файлов с одновременным доступом
От: Ночной Смотрящий Россия  
Дата: 28.01.22 19:02
Оценка:
Здравствуйте, corpse56, Вы писали:

C>1. Если файл необходимо отредактировать (то есть скачать к себе, изменить и загрузить изменённый), пользователь запускает режим редактирования, при котором все остальные пользователи не могут загружать изменённый файл до тех пор, пока пользователь сам не закроет режим редактирования либо истечёт время, отведённое на блокировку. То есть все ждут, пока пользователь не закончит режим редактирования. Это похоже на пессимистическую блокировку, если я правильно понимаю.


C>2. При скачивании файла, вычисляем его хэш, а когда пытаемся загрузить изменённый файл, то проверяем хэш. Если хэш изменился, значит даём отлуп и просим скачать файл заново. Это вроде как оптимистическая блокировка.


3. Файл делаем текстовый с максимально локальными изменениями, при параллельных правках выполняем мерж.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.