LINUX.ORG.RU

Нужен совет по хранению цельнотянутых файлов.


0

1

Задача — утягивать и сохранять картинки с web'а в удобном виде. Т.е., во-первых, с расширением (чтобы не дёргать контент на тему MIME), во-вторых, с сохранением близкого к оригиналу пути. Это нужно в первую очередь для og:image страниц. Пока подставляется классическая картинка — вопросов нет. Но когда начинаются URL с параметрами... Например:

http://fr.ill.in.ua/img/forall/a/13644/12.jpg?1391100872

Игнорировать при сохранении параметр нельзя. В общем случае он может менять картинку.

Создавать подкаталог 13644/12.jpg и в него уже класть файл (например, 1391100872 или 1391100872.jpg) — тоже нельзя. Картинка может отдаваться и без параметров, а одноимённые файл и каталог в Linux-ФС невозможны.

Пока приходит в голову только мысль делать замену «?» на какой-то символ, например, на «~», т.е. хранить в духе:

/storage/ua/fr.ill.in.ua/img/forall/a/13644/12.jpg~1391100872.jpg

Криво смотрится.

Есть, конечно, вариант забивать на оригинальный путь и сохранять, скажем, по md5(path), но это, во-первых, некрасиво, во-вторых, порождает проблему Мысли вслух. Предостережение от наступления на грабли..

Может, я упускаю ещё какой-то вариант?

★★★★★

Картинка может отдаваться и без параметров, а одноимённые файл и каталог в Linux-ФС невозможны.

Делать всегда в духе d-NAME (каталоги) и f-NAME (файлы) не вариант?

Deleted
()
Ответ на: комментарий от Deleted

«d» в каждом элементе пути будет некрасиво. Хотя тоже вариант. Но не думаю, что лучше первого, с подменой символа.

KRoN73 ★★★★★
() автор топика

Это ты для авиабазы? Я бы брал hash от полного имени и сохранял так. Но если тебе нужно будет hash->original_file_name - тогда гиммор.

А наиболее универсально (и геморно) - key-value db для этого прикрутить.

AKA UNIX@wkr.ru

anonymous
()
Ответ на: комментарий от KRoN73

В случае символа сам символ может быть в исходных данных. В этом случае это неважно.

Deleted
()

Пользуясь тем, что имя файла — тоже часть пути, предлагаю просто url-кодировать всю ссылку на файл и хранить его с таким именем. Подсмотрено в кеше pip:

http%3A%2F%2Fwww.mindrot.org%2Ffiles%2Fpy-bcrypt%2Fpy-bcrypt-0.2.tar.gz
http%3A%2F%2Fpypi.python.org%2Fpackages%2Fsource%2Fs%2Fssh%2Fssh-1.7.14.tar.gz
anonymous
()
Ответ на: комментарий от Felagund

base64

Это вариант последнего рассмотренного мной способа. Мало чем лучше md5, только что обратимость.

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Подразумевается масштаб в миллион файлов (порядок величины). Плюс возможность сохранять файлы с длинными путями. Длина имени файла на Linux-ФС весьма ограничена, длина ссылки (даже без учёта urlencode) очень и очень часто больше 255 символов выходит. Так что такой вариант мало подходит. И, в общем, является тоже вариацией упомянутого мной метода с заменой символа.

KRoN73 ★★★★★
() автор топика

Хранить данные в имени файла не очень удачная затея. А урл параметров может быть много. Я бы взял redis и туда складывал все данные в удобном виде(хеш, оригинальное название файла, mime, размеры, все параметры и время создания/модификации) а сам файл в md5. При необходимости по данным из базы можно будет воссоздать путь(или близкий к нему) и делать инкрементальные бекапы будет просто.

northicewind
()
Ответ на: комментарий от northicewind

Хранить данные в имени файла не очень удачная затея

Это не хранение данных, это удобный для редкого, но встречающегося ручного разгребания формат имени файла :)

KRoN73 ★★★★★
() автор топика

БД

если действительно важно ЧПУ путей к картинками, для ручного разгребания то можно такой вариант:

домен - в виде пути сохраняешь полностью (тут нет особых проблем)

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

получится примерно такое:

/local/path/to/repo/proto/example.com.domain/magic-type-static-path[/path-length/path-encoding/other-path-property/]example/path/image.jpeg

и т.д.

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

А почему БД не хочешь задействовать?

swwwfactory ★★
()
Ответ на: БД от swwwfactory

можно такой вариант

Это и получается фактически нынешний мой вариант :)

А почему БД не хочешь задействовать?

Она и задействована. Оригинальный URL, MIME, статистика и т.п.

Вопрос касается именно удобного формата хранения бинарников.

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от KRoN73

Это и получается фактически нынешний мой вариант :)

ну тогда что не устраивает - производительность ФС? ноды? возможности ФС исчерпаны полностью ;)?

Вопрос касается именно удобного формата хранения бинарников.

тебя настораживет что-то в тривиальном хранении файлов на диске?

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

может тогда посмотреть в сторону специализированных БД для аттачей типа couchbase (новый форк - активно пилится, пока не стабилен)/couchdb (сильно устаревает).

swwwfactory ★★
()
Последнее исправление: swwwfactory (всего исправлений: 1)
Ответ на: комментарий от swwwfactory

ну тогда что не устраивает

Я же писал — как-то не очень красиво и изящно. Потому и пошёл с вопросом, вдруг коллективный разум придумает лучше :)

может тогда посмотреть в сторону специализированных БД для аттачей типа couchbase

Я пока не верю базам данных на таких объёмах (десятки гигабайт, под сотню). Тут с единицами гигабайт геморроя оберёшься, когда сталкиваешься со сбоями/восстановлениями/бэкапами/обновлениями/модификациями/конвертациями/etc. Расчёт, всё же, на «пожизненное» хранение. Нынешним архивам и базам уже до 15 лет. Много уже с чем сталкиваться приходилось. Так что надёжнее голой ФС и пофайловых данных ничего нет. Но там свои геморрои, от малой скорости до проблем репликации/бэкапа (rsync на миллионе файлов в сотне тысяч каталогов — это жесть). Идеального решения пока не нашёл :)

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Упс. Упустил анонимные ответы :)

Сохранять в «12.jpg?1391100872»?

MIME определяется по контенту. На нагрузках чревато боком.

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Это ты для авиабазы?

Да, в первую очередь.

Я бы брал hash от полного имени и сохранял так.

Да, я рассматривал этот вариант, в списке — четвёртый.

Но если тебе нужно будет hash->original_file_name - тогда гиммор.

Угу. БД тут не поможет, поскольку такая задача обычно возникает при ручном анализе каких-то проблем. И прыгать в БД и обратно становится геморрно.

А наиболее универсально (и геморно) - key-value db для этого прикрутить

В отсутствии задач индексированного поиска часто проще попутные данные сохранять в .json, одноимённый с файлом. Я такое практиковал ещё лет 15 назад, только с .txt :)

KRoN73 ★★★★★
() автор топика

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

sdio ★★★★★
()
Ответ на: комментарий от anonymous

А наиболее универсально (и геморно) - key-value db для этого прикрутить.

оно уже есть. xattr называется.

emulek
()
Ответ на: комментарий от KRoN73

Я пока не верю базам данных на таких объёмах (десятки гигабайт, под сотню).

можно ведь потестить, если чо - все равно придется искать решения, ведь впереди еще больше нагрузка будет только.

Нынешним архивам и базам уже до 15 лет.

солидно. Твой опыт просто бесценен, так что занятно.

Оракл (и другие(колоночные наверное)) и постгрес как бесплатная альтернатива рассчитаны на гигантские объемы как считается...

swwwfactory ★★
()
Последнее исправление: swwwfactory (всего исправлений: 1)
Ответ на: комментарий от swwwfactory

можно ведь потестить

Большие объёмы и на реальных нагрузках сложно тестировать. Приходится разворачивать всю инфраструктуру, конвертировать базы... Масса усилий. И если всё хорошо, то ладно, а если потом ещё откатываться? Да ещё перенося назад то, что накопится за время тестов? Это ад начинается :)

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

Но пока тут тоже идеального решения не нашёл. Хочется, чтобы:
— Репликация была, естественно, мастер-мастер
— Полностью децентрализованная (чтобы отказ мастера не сказывался на сети в целом)
— Была возможность на лету подключать/удалять ноды
— Производительность падала бы не сильно, не больше, чем «в разы» по сравнению с голыми ФС.
— И это была бы классическая ФС или хотя бы имелись нормальные драйвера для популярных веб-серверов (nginx, lighttpd), или высокопроизводительный nfs-доступ и т.п.
— Не требовало особых ядер Linux, чтобы работало на любом VPS.

В итоге получается, что какой вариант не рассматривай, одного-двух пунктов до подного варианта не хватает :) Фактически выбирать сейчас приходится между GridFS (nginx-gridfs однопоточный, блокирующий, есть жалобы на надёжность... Переключение конфигураций на лету невозможно) и Openstack Swift (не файловая система, документохранилище).

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от KRoN73

распределённым

Производительность падала бы не сильно, не больше, чем «в разы» по сравнению с голыми ФС.

/0

emulek
()
Ответ на: комментарий от KRoN73

— Полностью децентрализованная (чтобы отказ мастера не сказывался на сети в целом)

полезен такой подход в этом плане - все ноды равноправны, нет мастера. В некотором смысле есть некоторые идеи для вдохновения у DCVS-систем, торентов

— Была возможность на лету подключать/удалять ноды

это эрланг так умеет штатно

— Производительность падала бы не сильно, не больше, чем «в разы» по сравнению с голыми ФС.

сейчас в моду входят легковесные контейнеры-виртуалки фактически для одного application - так-что производительность не всегда важна. В конце-концов кэшировать.

Большие объёмы и на реальных нагрузках сложно тестировать. Приходится разворачивать всю инфраструктуру, конвертировать базы... Масса усилий. И если всё хорошо, то ладно, а если потом ещё откатываться? Да ещё перенося назад то, что накопится за время тестов? Это ад начинается :)

виртуализация ведь для экспериментов.

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

или высокопроизводительный nfs-доступ

вроде как nfs выходит из моды и тормознут.

кстати, да - классическое: наращивание мощностей за счет легковесных, дешевых нод

VFS, как вариант и посмотри в сторону эрланга или эликсира (то-же самое, но в ООП-обертке руби-подобное)

swwwfactory ★★
()
Последнее исправление: swwwfactory (всего исправлений: 1)
Ответ на: комментарий от swwwfactory

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

Да, но если производительность ноды с распределённой ФС будет в 10 раз ниже, чем у голой ФС, то чтобы компенсировать падение, потребуется 10 нод. Нафига такая «экономия»? :) Падение в 2-3 раза я ещё могу простить из-за большего удобства репликации/бэкапа, но не более того :)

виртуализация ведь для экспериментов

Практика говорит, что никакие разумные тесты не вскроют всех проблем, что вылезут после начала реальной эксплуатации :) Откатываться реально иногда приходится.

Кстати couchbase вроде умеет масштабироваться

Но это не ФС. Тогда можно и на тот же Swift смотреть, что я упоминал выше :)

вроде как nfs выходит из моды и тормознут

Но используется как способ классического доступа к некоторым распределённыс ФС, например, Gluster FS.

как вариант и посмотри в сторону эрланга или эликсира

В том-то и вопрос, что ради legacy хочется использовать распределённые ФС с классическим доступом. Иначе проще начать использовать провереннык документоориентированные хранилища.

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от KRoN73

Ну тогда можно так -

md5(path)[0:3]/md5(path)[3:6]/md5(path)[6:].ext

pi11 ★★★★★
()
Ответ на: комментарий от anonymous

couchbase /= couchdb

У couchbase даже SDK под эрланг нет.

ну если у них версия enterprise платная, то не удивительно - наверное «зажали». Хотя, если есть исходники, то достучаться от эрланга к эрлангу не будет очень сложно (сходно с ситуацией с рабитом и в некотором смысле с ejabberd).

Возможно, что в этом нет особой необходимости в конце концов.

swwwfactory ★★
()
Ответ на: БД от swwwfactory

Плюсую БД. Плюс маленький серверок, чтобы смотреть эти картинки не в ФС, где хз что увидишь, а в браузере.

Miguel ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.