Сайт - доска объявлений, все изображения хранятся в одной папке, количество порядка 40 тысяч. Выводятся изображения напрямую, просто через урл (src="/imgs/1253573.jpg") Если ли смысл раскидать на поддиректории (по подразделам сайта например), большой ли будет выигрыш в ресурсах или скорости загрузки? Есть ли какие рекомендации на количество файлов в директории, после которых уменьшается скорость или увеличивается нагрузка?
Ответ
Введение
Разбивать однозначно стоит, если кол-во файлов превысит 5-7 тысяч. При 10к файлов в одной папке файловой системе уже обычно "стает плохо" - открытие файла отрабатывает дольше, растет нагрузка на диск. При 10к файлов в папке просто удалить все файлы уже было накладно (то есть, просто rm * уже просто так не работает - баш пытается развернуть * в список имен, этот список собрается долго, но потом он оказывается слишком длинным и баш не может выполнить команду. Правда где то в 2011-2012 это чуточку пофикисили, но все равно тяжело). У меня был опыт с подобным и несколько попыток переписать "правильно".
Теория
Стоит понимать, что разные файловые системы по разному реагируют. Например, ntfs при открытии папки пытаются обновить время последнего доступа. Если файлов много, то это на долго.
Сколько же теоретически можно вместить?
ntfs. Теоретический предел 2 в 32. Реальный - порядка 100k. Но пишут, что все тупит сильно. Также в msdn написано, что GetTempFileName не будет работать, если в каталоге с временными файлами больше 65535 файлов.
ext3. тут все сложно, максимальное кол-во файлов нужно смотреть.
ext4 - также, как и у ntfs, 4миллиарда.
Можно ещё почитать другой вопрос на SO - Максимальное количество файлов в папке Linux и Windows
Способ первый
Способ складывания по датам плох - он не равномерный. То есть, будут папки, где лежит много файлов и папок, где файлов почти нет. Так как папки в большинстве файловых систем не бесплатны. Второй недостаток - сложность шардирования. То есть, если размер файлов начинает превышать размер файловой системы, то начинаются проблемы. Ещё один недостаток - дубликаты. Их очень сложно отслеживать. Но у этого способа есть только один хороший плюс - легко найти старые файлы.
Способ второй
Но есть лучше способ, проверенный и используемый многими. Перед помещением файла в "хранилище", для файла считается md5/sha1. Теперь, на основании этого хеша формируется "путь для хранения". Я применял такой - первые два символа определяют папку, в котрой создается папка, имя которой совпадает с следующими двумя символами. А сам файл храниться внутри папки. Пример. Допустим есть файл "test.jpg" и md5 сумма от его содержимого такая "b3e6b7290309113a2d2b392bf1e2084e". Само хранилище находиться в /srv/archiv. Значит этот файл будет храниться по такому пути
/srv/archiv/b3/e6/b7290309113a2d2b392bf1e2084e_test.jpg
Я все таки оставил оригинальное имя файла. Иногда оно нужно. Но можно сохранять имена файлов в базу, тогда можно будет и не писать его.
Плюсы этого способа.
равномерное распределение файлов по каталогам (обеспечивается хэш функцией).
легко разнести файлы по серверам. К примеру, первые два символа могут определять имя сервера в кластере (а сами кластера подмонтированы внутрь).
легко выявляются дубликаты - у них будет одинаковый хэш.
если допустить, что файловая система легко держит 1000 файлов в папке, то вся система сможет удерживать около 65миллионов файлов (256*256*1000). Если брать минимальные файлы (по 4к), то это как минимум 250 гигабайт (плюс накладные расходы файловой системы, обычно это 10-20 процентов от размера).
использование в паре с этим способом ещё и базы данных сильно расширяет возможности.
Минусы:
хэширование не бесплатно.
теоретически может оказаться, что у двух разных файлов может оказаться одинаковый хэш.
сложно удалить "старые файлы", но find может помочь.
Готовые решения
Есть пример реализации на php - хабр
На посмотреть:
Хранение и доставка контента, Олег Илларионов (ВКонтакте)
Организация хранения данных, Кортунов
Комментариев нет:
Отправить комментарий