Как правильно хранить файлы на веб-сервере?

Рейтинг: 4Ответов: 2Опубликовано: 15.04.2015

Я бы хотел задать кое-какие вопросы о построении каталогов и хранении в них файлов (картинок, к примеру).

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

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

Многие советуют делать это след. образом: Вкратце опишу, генерируем название файла с помощью md5 хэша. Затем, берем первые 2 символа из название и создаём папку и туда помещаем все файлы, которые начинаются на одни и те же символы, подобным образом мы можем создать 256 папок в которые, к примеру, мы можем поместить по 1000 файлов. Разумеется, можно делать вложенные уровни из 3 и 4 символа из 5 и 6 и тд.

Но я не могу понять, что будет, если одна из папок забьется гораздо раньше чем другие? Как в таком случае быть?

Мой вариант, который пришел в голову (Думаю, я не первый): Создаем папку с числом текущего года, к примеру, затем текущего месяца и в папке с числом месяца создаем папку с днем месяца и в ней создаем папку с названием 1 и забиваем её до тех пор пока в ней не будет 1000 файлов, затем создаем папку с числом 2 и забиваем её, ну и в таком же духе и дальше.

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

Для наглядности: 2015/04/15/1

Забиваем папку с названием 1 до 1000 файлов, затем создаем папку с названием 2, после 3 и так до 1000

Закончился день, тогда создаем в папке 04 папку 16 и дальше по описанному принципу работаем. Разумеется, папки создаются только тогда, когда в них грузятся файлы.

Какие у вас мысли по этому поводу? Какую структуру хранения файлов используете вы? И чем она хороша? Приемлема ли та структура которую описал я, с вашей точки зрения? Что скажете по поводу производительности?

Ответы

▲ 3

Ответ достаточно общий, без всякой привязки к PHP.

Если требуется поиск файлов по имени, то я бы попробовал все же сделать структуру, основанную на MD5 (или другой хэш-функции) в 16-ричном виде (для MD5 все имя это 32 символа от 0 до f), только не с жесткой организацией уровней каталогов, а с динамической.

Имена каталогов задаются, например, тройками символов. Соответственно, каталог может содержать до 4096 других каталогов.

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

Когда в каталоге соберется 4096 файлов мы проводим реорганизацию. Делаем по первой тройке символов имен файлов каталоги и перемещаем файлы в них.

Надеюсь, далее очевидно.

▲ 2

что будет, если одна из папок забьется гораздо раньше чем другие?

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

Чем система проще, тем она лучше работает.
В простой системе нечему ломаться.

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

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

Плюс можно перевести хэш из 16-ричной системы в 36-ричную, задействовав все буквы алфавита, а не только первые 6. Что сократит длину хэша и одновременно увеличит количество вариантов для разбивки, уменьшая необходимую глубину папок.