Хранение моей базы данных и файловой системы в синхронизации - программирование
Подтвердить что ты не робот

Хранение моей базы данных и файловой системы в синхронизации

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

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

Вариант 1: добавление ссылки на файл сначала

//Adds a reference to a file in the database
database.AddFileRef("newfile.txt"); 

//Stores the file in the file system
fileStorage.SaveFile("newfile.txt",dataStream); 

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

Вариант 2: сначала сохранить файл файла

//Stores the file
fileStorage.SaveFile("newfile.txt",dataStream); 

//Adds a reference to the file in the database
//fails if reference file does not existing in file system
database.AddFileRef("newfile.txt"); 

Этот вариант лучше, но позволит кому-то загрузить файл в систему, на которую никогда не ссылаются. Хотя это можно было бы исправить с помощью функции "Очистить" или "CleanUpFileSystem", которая удаляет любые файлы без ссылок. Этот параметр также не позволит сохранить файл с использованием значения первичного ключа из базы данных.

Вариант 3: ожидающий статус

//Adds a pending file reference to database
//pending files would be ignored by others
database.AddFileRef("newfile.txt"); 

//Stores the file, fails if there is no 
//matching pending file reference in the database
fileStorage.SaveFile("newfile.txt",dataStream); database

//marks the file reference as committed after file is uploaded
database.CommitFileRef("newfile.txt"); 

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

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

4b9b3361

Ответ 1

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

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

Это дает вам дедупликацию бесплатно. Однако удаление становится сложнее. Я рекомендую ночной сбор мусора.

Ответ 2

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

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

Вариант 3 не имеет никакого преимущества, но использует больше ресурсов.

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

Другие вопросы касаются того, как вы работаете с частичными загрузками и загрузками. Здесь вариант 2 может быть полезен, но вы также можете использовать второй файл "флаг", который создается до начала загрузки, и удаляется при завершении загрузки. Это поможет вам определить, какие загрузки были прерваны.

Ответ 3

Чтобы исправить недостаток, упомянутый в опции 1, я использую что-то вроде fileStorage.FileExists("newfile.txt"); и отфильтровываю результат, для которого он возвращает отрицательный.

В Python lingo:

import os
op = os.path

filter(lambda ref: op.exists(ref.path()), database.AllRefs())