Как стать автором
Обновить

Хранение файлов

PHP *
За последнее время мне пришлось активно работать с сайтами, которые большие объемы информации хранят в файловой системе. Это разнообразные сайты фото и файловых хостингов, а также сайты с загрузкой видео контента, некоторые сайты проектировались и программировались мной с нуля, некоторые переписывались, дописывались или «приводились в порядок».
Должен отметить, что хранение файлов в файловой системе является для многих программистов областью, которая проходит мимо их внимания.
Для начала дам небольшой обзор распространенных ошибок:
1. файл храниться в файловой системе под кириллическим названием. Собственно, происходит следующее: пользователь загружает файл под именем, скажем, «безымянный-1.jpg», программист с тем же именем запихивает его в каталог, в котором хранятся файлы. Надеюсь, не нужно объяснять какие проблемы это за собой может повлечь?
2. файл храниться под тем же названием, под которым он был загружен пользователем, но символы не входящие в латинский алфавит транслитерированы. Уже лучше, но все равно данный способ вызывает множество проблем, например пользователи очень любят грузить файлы с одинаковыми названиями))) И дело не в том, что они такие злые, например мой фотоаппарат после каждой очистки карты памяти начинает нумерацию фотографий с 00001.
И третья самая распространенная ошибка:
3. Хранения в директории количества файлов превышающих возможности файловой системы. Рассмотрим эту ситуацию на конкретном примере, переписывал я файловый хостинг, большой, на момент переписывания объем информации вплотную приближался к четырем терабайтам, и это притом, что 80 процентов файлов были картинками. Все файлы на диске (дисков было 4 каждый по терабайту) случайным образом раскидывались по двум десяткам директорий, и так до заполнения диска, потом программа переходила на следующий диск. В результате для того что бы открыть директорию вебсерверу требовалось около трех секунд. Согласитесь, это катастрофически много. В каждой директории на диске находилось около двадцати тысяч файлов.
Проанализировав несколько таких ситуаций, я попробовал вывести способ хранения файлов, который бы удовлетворял следующим условиям:
1. директория не должна тормозить, то есть в одной директории не должно храниться более 1000 файлов или каталогов (число взято с запасом).
2. имена файлов не должны повторяться.
3. желательно не хранить две копии одного файла.
После некоторых раздумий, я пришел к следующей схеме, которой и хочу поделиться с коллегами программистами.
Начну с последнего требования не хранить две копии файла. Для определения целостности файла давно и вполне успешно используется md5 хеш для php, эта задача решается функцией md5_file(filename), которая вычисляет MD5 хэш файла, имя которого задано аргументом filename используя алгоритм MD5 RSA Data Security, Inc. и возвращает этот хэш. Хэш представляет собой 32-значное шестнадцатеричное число.
Если два файла одинаковы у них и хеш будет одинаков, если разные — то разный. Сейчас в меня «полетят камни» сопровождающиеся рассуждениями о коллизиях и ненадежности md5. Отвечу по порядку md5 не надежна? Но мы же не ставим задачу обмануть «вероятного противника»! Мы просто получаем уникальный идентификатор файла и все. А по поводу коллизий… я не настаиваю на повторении моего метода один в один, используйте другую функцию. Только задумайтесь, два в двести пятьдесят шестой степени это — очень много! Если мне говорят, про возможность возникновения коллизий, я прошу человека привести пример двух строк или двух файлов, md5 хеш, которых одинаков… пока еще мне не было приведено такой пары так, что возможность является чисто теоретической.
Пункт второй – «имена файлов не должны повторяться, напрямую вытекает из третьего. Если в качестве имени файла на диске мы используем строку его md5 хеша, то имена файлов не повторяются (реальные имена файлов (те, которые загрузил пользователь), мы можем хранить в базе данных). В случае загрузки пользователями двух одинаковых файлов, мы получаем у них одинаковые имена. И первое — файлы не будут дублированы, второе — мы не беспокоимся по поводу имен в директориях.
Теперь чуть более сложно, по поводу хранения файлов на диске. Я создаю структуру вложенных каталогов, опираясь на имена файлов. Здесь тоже полный простор для фантазии. Я ни в коем случае не призываю слепо копировать мой способ. Обычно я делаю два, три уровня вложенности каталогов. Первый уровень — это первые две буквы названия файла (не забыли, название файла это его md5 хеш!); второй уровень это третья и четвертая буквы…
Каждый уровень вложенности дает мне * на 256 каталогов.
То есть, если в один каталог я могу загрузить не более 1000 файлов, то при одном уровне вложенности я могу безопасно разместить на диске 256 000 файлов; при двух уровнях вложенности – 65 536 000; при трех – 16 777 216 000 и так далее. Длинна строки md5 хеша позволяет нам сделать 16 уровней вложенности в каталогах. На мой взгляд, этого хватит для обеспечения работы самых емких дисков. Хотя, исходя из практика, обычно, и трех уровней хватает «за глаза» для проектов любой сложности.
P.S. Обновленный и развернутый вариант (написан по итогам обсуждения)
Теги:
Хабы:
Всего голосов 25: ↑13 и ↓12 +1
Просмотры 18K
Комментарии Комментарии 45