Pull to refresh

Comments 73

Я может не совсем компетентен, но всегда интересовал вопрос, что курят люди делающие такое:

Как создать свою файловую систему на основе blob полей в базе данных. Почему это удобно.

Создание файловой системы в БД, которая сама является набором файлов в нормальной файловой системе.

Чтобы будущий разработчик принявший вымерший проект для рефакторинга застрелился предварительно перерезав семью?

«Застрелился» можно опустить. Хансу 6 лет осталось всего.
https://docs.mongodb.com/manual/core/gridfs/ — там описание кейсов, в которых подобное может быть полезным (но да, лепить это руками я бы не стал, лучше взять одно из многих готовых решений).
Получил как-то «в наследство» CMS с такой парадигмой, много лет после этого задаюсь этим вопросом и видимо настал момент узнать ответ.
UFO just landed and posted this here
CREATE TABLE FILES_ (
    ID                  BIGINT,
    DATA                TIMESTAMP,  --Дата добавления файла
    DATA_DEL            TIMESTAMP,  --Дата удаления файла

IMHO, было бы логичнее использовать слово «date», а не «data».

И вообще именование полей очень спорное. Например, вместо «USER» и «USER_DEL» я бы использовал «created_by» и «deleted_by» — тогда бы сразу отпала необходимость в комментариях.

Кроме того, для хранения файлов лучше использовать решения на базе NoSQL, например, упомянутый выше GridFS или HDFS.
Да можно как угодно обозвать. Это просто пример. Но вообще я всегда пишу «Data» (тут автоматом тоже так обозвал) ибо «Date» — зарезервированное слово, оно в любом случае с приставкой какой-то должно идти. Можно конечно с кавычками, но это просто неудобно.

GridFS — как вариант. Но когда мне пришлось все это делать, я просто не знал о ней. Возможно я бы тогда и не заморачивался своей системой.
Но видите, во всем своя польза, получилась альтернативная структура, которую можно сделать самостоятельно. В свое время я никакой подробной статьи по использованию blob полей для хранения файлов не нашел. Вот написал ее, пусть будет.
Можно конечно с кавычками, но это просто неудобно.

Фу таким быть. Это вот после таких "неудобно" приходится каждому новичку объяснять, что "в Date у нас дата, Customar_ID — это по опечатка оплошности, и хранится там не Customer.ID, а LegalEntity.ID" и т.д.

в Date у нас дата
Ну правильно же :-)

Вот сами руки написали, клянусь макаронным монстром!

UFO just landed and posted this here
Данный способ лишен основных уязвимостей веб приложений при загрузке файлов

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


Не городить же единый запрос в несколько БД.
Тут есть некоторая избыточность данных в этих двух таблицах

В основной базе в таблице files хранится путь к файлу. В таком варианте ничего городить не надо, запрос идет только в основную БД. После проверки прав содержимое так же отдается через stream. Для удобства переноса можно адрес сервера в отдельном поле хранить.


Все, у нас файл записан в файловую БД. На веб-сервере его нет.

"Все, у нас файл записан в файловое хранилище на другом сервере. На веб-сервере его нет."
В чем принципиальная разница?


Тут хочу обратить внимание на типовую ошибку. Перед <?php и после ?> не должно быть никаких символов – иначе ничего не получится.

Рекомендуется не закрывать тег, если в файле есть только PHP-код. Это так, к сведению.


Т.е. когда пользователь кликает на ссылку file_b.php?id=123, скрипт должен дернуть другой скрипт, который считает в себя данные из blob файла

Зачем? Что мешает разархивировать в этом же скрипте?


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

Да ну? Вы для программистов статью написали или для менеджеров?)


Следовательно, в задачах должна быть не ссылка, а некое “окно” в Диск, в котором задача будет видеть только свои файлы.

Эмм. Чем это отличается от таблицы tasks__files (task_id, file_id, ...)?


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

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


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

comments__files


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

FontAwesome, glyphicons

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

Кроме того, такой подход может пригодиться в облаках, где принято делать stateless-контейнеры.
Эти уязвимости есть, если вы загружаете файл на тот же сервер, где работает интерпретатор PHP, и к тому же есть прямой доступ из интернета к загруженным файлам. У вас отдельный сервер для файлов с доступом через скрипт. Так что тут нет разницы, хранить их в базе или на диске. Если я правильно понимаю, из преимуществ остается только удобство бекапа средствами БД.

1) Неизвестно имя файла, т.е. ссылкой его дернуть не получится
2) Во вторых можно грузить в каталог ниже каталога веб сервера
3) В третьих он грузится на миг, т.е. только на время работы скрипта, скрипт этот файл после загрузки в БД с веб сервера удалит.

При извлечении аналогично, он только миг присутствует на веб сервере.

В основной базе в таблице files хранится путь к файлу. В таком варианте ничего городить не надо, запрос идет только в основную БД. После проверки прав содержимое так же отдается через stream. Для удобства переноса можно адрес сервера в отдельном поле хранить.

Примерно так и сделано. Данные в файловой базе — избыточны. Но они удобны для анализа. Конечно можно без них сделать. С ними просто удобнее в случае работы именно с данным файлов, не надо дергать основную базу.

«Все, у нас файл записан в файловое хранилище на другом сервере. На веб-сервере его нет.»
В чем принципиальная разница?

Веб сервер не «резиновый». В него не влезут файлы 1000 клиентов… Масштабируемость нужна. При необходимости покупается новый сервер, его адрес прописывается в настройках и на нем создаются базы новых клиентов и туда все пишется.

Зачем? Что мешает разархивировать в этом же скрипте?

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

Да ну? Вы для программистов статью написали или для менеджеров?)

Да, вы правы, это я погорячился )

Эмм. Чем это отличается от таблицы tasks__files (task_id, file_id, ...)?

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

И да и нет. Можно и так, но в моем случае например лучше через хэши. У меня встроенный язык программирования и файлы могут быть приложены где угодно в системе, в любом месте страницы любого раздела, даже в нескольких местах на одной странице + должны учитываться входные данные в страницу, например у одной задачи одни файлы, у другой дургие. Входные данные — может быть тоже не один параметр а 2-а,3-и...,10-ять. Поэтому удобнее было через хэши. Он всегда будет уникальный у уникальных данных. Да и в смысле быстродействия на мой взгляд лучше, индекс по одному полю с уникальными значениями.
Но реализация через таблицы многие-ко-многим — тоже вполне может иметь место.
UFO just landed and posted this here
1) Неизвестно имя файла, т.е. ссылкой его дернуть не получится

Если не разрешать доступ к файловому серверу из интернета, то тоже ссылкой его дернуть будет нельзя. Вы же к базе не даете открытый доступ.


2) Во вторых можно грузить в каталог ниже каталога веб сервера

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


3) В третьих он грузится на миг, т.е. только на время работы скрипта, скрипт этот файл после загрузки в БД с веб сервера удалит.

Если файлы грузятся на отдельный сервер, то будет точно то же самое.


С ними просто удобнее в случае работы именно с данным файлов, не надо дергать основную базу.

А как же проверка прав доступа?


Веб сервер не «резиновый». В него не влезут файлы 1000 клиентов

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


Смотря чем архивирован. Для 7z очень сомневаюсь. Можно только zip насколько я знаю. Это одна из реализаций.

Нет, что мешает вызвать exec('7z ...') в этом же скрипте, без использования CURL?

1) Неизвестно имя файла, т.е. ссылкой его дернуть не получится

Если не разрешать доступ к файловому серверу из интернета, то тоже ссылкой его дернуть будет нельзя. Вы же к базе не даете открытый доступ.

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

2) Во вторых можно грузить в каталог ниже каталога веб сервера

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

3) В третьих он грузится на миг, т.е. только на время работы скрипта, скрипт этот файл после загрузки в БД с веб сервера удалит.

Если файлы грузятся на отдельный сервер, то будет точно то же самое.


Да, можно так же грузить. Только на веб сервер нужно монтировать сетевые диски. Ставить самба сервер. Это как варинат да, но на мой взгляд менее удобно. В принципе можно заниматься монтированием и писать пути.

Смотря чем архивирован. Для 7z очень сомневаюсь. Можно только zip насколько я знаю. Это одна из реализаций.

Нет, что мешает вызвать exec('7z ...') в этом же скрипте, без использования CURL?

Как что мешает? А какой файл вы собрались делать exec('7z ...')? Нужно файл добыть сначала. Это делается CURL.
а со случайным, какое имя файла будет при загрузке — неизвестно заранее

Почему неизвестно? В таблице files делается поле filename (или filepath). Информация о файле в базе есть, разница в том, что контент файла там не хранится.


Только на веб сервер нужно монтировать сетевые диски.

Зачем? Если например использовать FTP, то достаточно вызова ftp_put().


Как что мешает? А какой файл вы собрались делать exec('7z ...')?

Вызывается скрипт file_b.php?id=123. В нем написано примерно такое:


$fileRow = getFileRowById($_GET['id']);
$randomName = 'random_name.zip';
file_put_contents($randomName, $fileRow['FILE_DATA']);
exec('7z ' . $randomName . ' ...')

// ... отправка разархивированного файла

Может и умеет, я просто пример автора преобразовал)

а со случайным, какое имя файла будет при загрузке — неизвестно заранее

Почему неизвестно? В таблице files делается поле filename (или filepath). Информация о файле в базе есть, разница в том, что контент файла там не хранится.

Ну мы же рассматриваем безопасность, т.е вариант со стороны нападающего. Понятно что серверу известно имя файла, но нападающему нет. Он не сможет его по ссылке выполнить.

Только на веб сервер нужно монтировать сетевые диски.

Зачем? Если например использовать FTP, то достаточно вызова ftp_put().

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

Как что мешает? А какой файл вы собрались делать exec('7z ...')?

Вызывается скрипт file_b.php?id=123. В нем написано примерно такое:

Да, тут вы правы! Действительно с file_put_contents может получиться. Не приходило в голову. Потестирую, если все ок будет обновлю статью.
UFO just landed and posted this here
Понятно что серверу известно имя файла, но нападающему нет. Он не сможет его по ссылке выполнить.

Тогда я все правильно сказал в прошлый раз. "Если не разрешать доступ к файловому серверу из интернета, то тоже ссылкой его дернуть будет нельзя.". А если на файловом сервере нет PHP, то и с известной ссылкой нападающий его не выполнит.

UFO just landed and posted this here
UFO just landed and posted this here
если вы почитаете статьи автора по ссылкам в начале, вы увидите что автор живет в своей, уникальной вселенной. В частности работа с датами это же просто лютый треш!
TerraV — улыбнуло :)
Но вообще это просто нестандартный подход. Он имеет свои плюсы при использовании в определенных задачах. Просто никто не может на него посмотреть с другой стороны, не как привыкли.
UFO just landed and posted this here
Вы хотите индексы по блобам делать?..
Хранение файла вне веб-сервера, в любом случае оверхед.

Отдача файла посредством того же nginx в разы более легкая задача в сравнении с отдачей этого же файла из БД да еще и через приложение.


И Oracle и MSSQL Server для этих целей сделали отдельное легковесное апи, которое позволяет отдавать файл напрямую из БД минуя приложение.
В случае MySQL и FireBird такая возможность отсутствует.

Хранение файлов в блобах — это очень дорогой в финансовом отношении способ.
Обычно СУБД работают на серверах на быстрых винчестерах 10K, 15K, и такие винчестеры,
особенно фирменные, стоят как половина самого сервера, а ёмкость имеют небольшую — 300, 600 гигов.

В то время как для хранения файлов достаточно винтов 5400 или 7200 в дисковой полке.
Готов поставить пиво, что такого рода извращения нужны в случаях написания 'велосипедов'.
UFO just landed and posted this here

Боже, какая все же печаль....


Итак, по пунктам:


  • Хранить файлы в БД нужно в достаточно редких и исключительных случаях (или тогда когда у вас ну очень простой бложик и вы хотите иметь абсолютно весь контент в одном месте — БД). Поэтому для большинства случаев правильный ответ — не хранить.
    Тогда когда вам это потребуется — вы будете знать достаточно чтобы это сделать. Чаще всего это моменты связанные с шардингом и репликацией данных между шардами. И интенсивной работой с самими файлами.
  • В обычном случае в БД храним метаинформацию о файле
    — реальное имя файла загруженного пользователем
    — размер
    — дату
    — путь где хранится файл (включая служебное имя сгенерированное вами) и возможно имя файлсервера
  • На файлсервере вы встраиваете дерево с учетом того чтобы не хранить более 1000-2000 файлов в одном каталоге. Для этого можете именовать файлы при помощи хеширующей функции и разбивать на группы по части имени.
  • Сам файлсервер может быть подключен к CDN

Все.

Извиняюсь, ниже коммент, не в то поле вставил.
UFO just landed and posted this here
Оправдание чему? :-D
UFO just landed and posted this here
Мне жаль вас огорчать, но вам к окулисту и в первый класс школы.
Для изучения чтения
UFO just landed and posted this here
К счастью здоровым вроде меня она и не нужна.

А вам я крайне рекомендую перечитать и вникнуть в текст.
Ну и определиться с тем, что же вы считаете велосипедами…
Ок, Fortop.

Давайте по полочкам. Рассматриваем мы бесплатную СУБД.
Oracle и MSSQL Server нет. Денег на них нет, а есть только бесплатный Firebird. У стартапов такое бывает весьма часто. Надо при минимуме бабла, выжать максимум производительности.

Решить следующее:

Файлы пользователей должны храниться вне веб сервера. Система должна быть распределенной и неограниченно масштабируемой. Файловых серверов может быть сколько угодно и они могут добавляться в процессе работы. Нужно иметь возможность достаточно просто организовать миграцию файлов клиента на другой сервер при необходимости (например заполнено 70% места, добавили еще сервер, 35% оставить на старом, 35% переместить на новый так чтобы никто ничего не заметил, и дальше равномерно раскидывать новых клиентов по двум серверам. Потом следующий сервер и т.д.).

Файлы аккаунта должны бекапится (отдельный файл архива со всеми файлами). С возможностью передачи архива на оборудование клиенту по графику (если он настроит свой ftp в системе планирования бекапов)

Какие варианты я вижу для решения этой задачи:
а) Samba-server и cifs, класть файлы локально вне каталога веб сервера
б) Загружать их на файловый сервер по ftp
в) Хранить их в базе данных (каждому аккаунту своя база данных с которой он работает)

GridFS я никогда не использовал и возможно мое мнение будет субъективное, но я не вижу никаких преимуществ, так же надо файл туда положить, так же его взять оттуда и произвести над ним операции. Разве что возможно чуть быстрее будет, чем с реляционной БД

Отдача файлов.
1) В любом случае это не прямая ссылка, это скрипт с header. Как минимум соображения безопасности это диктуют.
2) Файл может быть сжатым. На мой взгляд для сжатия лучше использовать стандартные архиваторы (они работают эффективно). Перед отдачей пользователю, его надо разархивировать.
В случаях б) и в) файл надо стащить на веб-сервер чтобы сделать эту операцию.
В случае а) можно сразу архиватором читать файл по сети, а оригинал сохранять на веб сервере.
3) Как отдавать.
Самый простой (но возможно действительно не самый эффективный) вариант — как описан в статье. Делаем нужный header и выводим в скрипт данные файла. После файл стираем.

Возможно вы правильно советуете через nginx, я этого не пробовал, но мне стало интересно, обязательно попробую. Почитал, можно через X-Accel. Он даже может взять их с другого сервера, насколько я понял. В документации сказано что так
location / files {
internal;
proxy_pass http://127.0.0.2;
}


Да, соглашусь, неплохо все. Но как же масштабируемость? А если много серверов откуда надо брать? Т.е. надо скриптом их грузить на этот сервер с которого потом будет отдача и header(«X-Accel-Redirect: /files/». $path);
Вообще предполагаю что можно сделать location / files1{}, location / files2{} и т.д. и в зависимости от того на каком файловом сервере и изымать по нужному пути, но описания этого я сходу не нашел, поэкспериментировать придется.
А вообще именно база данных для хранения файла была выбрана из соображений удобства. Просто бекапить, просто мигрировать на другой сервер, просто накатить новый. Купил железку, накатил проксмокс, сделал копию виртуалки, поменял IP, почистил, прописал ее настройки в базе распределения – все подхватилось и все работает. Так же файловая база в моем случае решает проблему хранения типа данных image в моем внутреннем языке программирования, но это мой индивидуальный случай.

Но вообще, если что подскажите, что решит описанные проблемы и будет удобно в эксплуатации, буду благодарен и обязательно изучу если не знаю. Но пока получилось решить так.
UFO just landed and posted this here
Файлы пользователей должны храниться вне веб сервера. Система должна быть распределенной и неограниченно масштабируемой.

Берете, значит, облачное хранилище (Azure Blob или S3) — и все, конец разговора.

Там исходные две посылки их режут

Денег на них нет…
… Надо при минимуме бабла, выжать максимум производительности.

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

Ну да, а место, на котором Firebird развернут, бесплатное

Без понятия :D
Одно я знаю точно Амазон и Азур жестоко дорого для более-менее равномерной нагрузки и без использования основной массы их фич.

Вот такое
RAM 64 GB DDR4 RAM
Hard Drive 2 x 4 TB SATA 6 Gb/s 7200 rpm

Перекрывает потребности практически любого стартапа, который в состоянии поднять один человек за 2-4 месяца

Масштабируемость? Распределенность?


(другое дело, что не факт, что они стартапам нужны, но автор же попросил)

Масштабируемость? Распределенность?

1. путем поднятия еще такого же сервера
2. в рамках цодов хетцнера или любого другого крупного хостера с аналогичными же тарифами

И, да, не из коробки.

Вот-вот. А когда начинаешь это реализовывать, в какой-то момент так задалбываешься, что дешевле купить у Амазона/МС. Мы вот даже не стали думать свое делать, а просто взяли облако, ибо намного предсказуемее.

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

При наличии хорошего админа об этом не задумываешься.
В свое время на проектах команды которую я вел использовалось свыше 200 виртуалок.
А сколько уж реальных серверов было — нас, как разработчиков, не сильно интересовало.

На проект я просил типовые инстансы в количестве 4-5 штук. (2 бек, 2 сфинкс, отдельно мемкеш, отдельно бд, отдельно статика)
И масштабировалось все путем клонирования оных и подброса под haproxy и nginx

На пике нагрузки на одном проекте могло быть 22 бека, 18 сфинксов, 1 БД, 2 с демонами, 2 мемкеша.

Вопрос в том, сколько стоит такая админская команда, опять-таки.

Вопрос в том, сколько стоит такая админская команда, опять-таки.

Я сильно удивлю, если скажу что админ был один? :)
И вел он не только нашу команду, но и еще как минимум 2 о которых я знал… :D

По его ЗП — без понятия.
Железо на пиках обходилось порядка 8 000 $ в месяц, это из того что краем уха слышал.

Да нет… но стоимость работы (а так же что делать, если он попал под автобус) — это все равно фактор.

Это вопросы не тимлида в общем случае, а техлида.

Но админ масштабируется примерно так же как и сервера. И как прочие разработчики.
Главное лишнюю бюрократию не разводить, которая крайне замедляет процесс реакции.

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

К сожалению двух команд под рукой не было, чтобы сравнить стоимость и уровень рисков между командой dash-специалистов и командой T-специалистов.
Это вопросы не тимлида в общем случае, а техлида.

Но в стартапах на 2-4 человека, как мы знаем, регулярно это один и то же человек… и на админа там тоже ресурсов нет.


В общем, каждый балансирует сам для себя.

Сейчас так нельзя по российскому законодательству. Хранить персональные данные можно только на территории РФ. 152-ФЗ, 242-ФЗ.

Стоимость же аренды виртуалок например на M8 впечатлит любого. За несколько месяцев аренды можно просто купить аналогичные б\у сервера и разместить их в датацентре по цене 2.5-3 тыс в месяц за 1U. Да и неизвестно какие мощности тебе на самом деле выделяют, не факт что как написано, а тут ты знаешь что у тебя есть.

В третьих. Нет поддержки второго уровня виртуализации. Я одно время продумывал вариант аренды со спящими виртуалками на случай физического выхода из строя оборудования, но вот просто взять и свою конфигурацию перенести не получится, нельзя у них сделать виртуалку например с проксмоксом и туда скопировать свою структуру. В общем этот вопрос в итоге решается дополнительным железом, где лежат копии виртуалок, которые можно быстро поднять. Это же железо можно юзать для хранения бекапов, логов и т.д.
Сейчас так нельзя по российскому законодательству. Хранить персональные данные можно только на территории РФ. 152-ФЗ, 242-ФЗ.

Речь вроде про хранение файлов шла. Ну и да, если вы храните персданные… а вы как оператор зарегистрированы? А система у вас сертифицирована?


За несколько месяцев аренды можно просто купить аналогичные б\у сервера и разместить их в датацентре по цене 2.5-3 тыс в месяц за 1U.

… и мы снова возвращаемся к вопросу о (запрошенных вами) неограниченной масштабируемости и распределенном хранилище.


Нет поддержки второго уровня виртуализации.

Что такое "второй уровень виртуализации", и зачем он вам нужен при хранении файлов?

1) Причем тут оператор. Этот закон ко всем относится. Если у вас на сайте регистрируется пользователь и он может оставлять какие-то свои персональные данные или данные по своим клиентам, все, только РФ.
У меня все в комплексе, в том числе файлы. Глупо хранить именно файлы за рубежом отдельно от всего остального…

Слушал недавно по бфм интервью кого-то из битрикса (не помню уже кто), по этому поводу. У них все на амазоне было и весьма непросто было переехать в РФ. Издержки сейчас выросли на треть вроде из-за этого.

У операторов по Яровой голова болит…

2) А что вас в данном случае смущает? Покупайте оборудование и ставьте дальше в датацентре.

3) Нельзя в облаке делать виртуалки внутри виртуальных машин. Проксмокс например требует от процессора поддержки аппаратной виртуализации, это у хостеров не поддерживается. Т.е. грубо говоря беря в облаке виртуальный сервер, вы не сможете на нем поставить гипервизор и внутри него сделать виртуалки.
А строить все в облаке с нуля вместо того чтобы скопировать структуру, на мой взгляд это просто мартышкин труд, тем более что это надо сделать просто на всякий случай.
Причем тут оператор. Этот закон ко всем относится.

При том, что если вы храните персданные, вы должны соответствовать не только требованию "только в РФ".


Глупо хранить именно файлы за рубежом отдельно от всего остального…

"Глупо" изобретать свои велосипеды.


А что вас в данном случае смущает? Покупайте оборудование и ставьте дальше в датацентре.

… датацентр бесконечный? Я уж молчу про географическую распределенность.


Нельзя в облаке делать виртуалки внутри виртуальных машин.

А зачем для хранения файлов виртуалка? Я больше скажу, для хранения файлов нужен только сервис, который обеспечивает… хранение файлов. Он есть, он работает.


А строить все в облаке с нуля вместо того чтобы скопировать структуру, на мой взгляд это просто мартышкин труд, тем более что это надо сделать просто на всякий случай.

"С нуля" — это ваше решение "давайте положим файлы сюда, давайте напишем такой-то код, блаблабла", вместо того, чтобы просто взять готовое решение "заливайте файлы такой-то HTTP-операций, читайте файлы такой-то HTTP-операцией".

О боже, lair… Если вы способны забить своим оборудованием датацентр… я думаю вы просто свой датацентр сделаете, 2 датацентра, 3, 4…

Хранение файлов это «одно из»…
Виртуалки затем чтобы не делать двойную работу. В данном примере с облаком — это резервный вариант. У вас поменялась структура и что, вам вместо того чтобы сделать копию надо менять структуру в облаке на аналогичную… это путь в никуда. Резервный вариант должен делаться копией, а не силами разработчиков переписываться.
Вообще как сказал один мой знакомый сисадмин: «виртуализация, это наше все».
Если вы способны забить своим оборудованием датацентр… я думаю вы просто свой датацентр сделаете, 2 датацентра, 3, 4…

Но зачем?


У вас поменялась структура и что, вам вместо того чтобы сделать копию надо менять структуру в облаке на аналогичную…

Эээ, зачем? Зачем мне вообще менять какую-то "структуру" в облаке?


Вообще как сказал один мой знакомый сисадмин: «виртуализация, это наше все».

Для него, возможно, это так. Но не для разработчиков.

  1. сколько угодно файловых серверов.
    • Можно разруливать через приложение, которое по функции определяет к какой шарде обращаться
    • Можно разруливать через nginx, где функцию определения шарды реализовать при помощи того же lua
    • Что из себя представляет функция? В простейшем виде, например, остаток от деления айди на количество серверов, или маппинг по регулярным выражениям от хеша имени файла и т.п.
  2. Отдача и проверка прав через скрипт и X-Accel-redirect заголовок
    Техника стара как мир, если погуглить, то можно найти даже решения с expired токенами в ссылке на скачивание
  3. Миграции при добавлении новых шард.
    Аналогично легко гуглится. В простейшем случае это несколько скриптов которые производят вычисление шарды по старому и новому методу (добавление или удаление шарды влечет за собой изменение функции).
    И затем выполняют копирование файлов на новый сервер (как и чем? Например, rsync)
    Процесс верификации может быть или одновременно с копированием (мы проверяем идентичность и доступность файла в новом месте), или отдельной задачей по завершению переноса.
    Если есть ошибки, то повторить копирование и/или выдать сообщение в лог для разбора.
    Процесс удаления старых файлов выполняется только при успешной верификации и так же может идти для каждого файла сразу при копировании, или пакетно для всех по завершении верификации.
  4. бекап выполняется для всей системы сразу и отдельно администратором.
    Бекап отдельного аккаунта иногда целесообразен, если подразумевается активное удаление/добавление файлов самим пользователем и приложение хочет предоставить возможность отката действий самого пользователя.
    В общем случае вместе с отправкой этого бекапа куда-либо это функция экспорта информации. Выполняется отдельным скриптом/модулем приложения.
  5. Компрессия/декомпрессия файлов не относится к общему случаю.
    Объём диска обычно дешевле процессорного времени, если вы не файл/фото хостинг
    Поэтому сжимать изначально — нет смысла, поскольку это относится к оптимизации.
    Лучше потратить время разработки на более критичные фичи.
  6. Компрессия/декомпрессия, и Linux и Windows умеют сжатие разделов целиком. То есть это можно настраивать вне вашего приложения и абсолютно прозрачно для него.
  7. Отдача, nginx умеет кешировать соответственно буде мы решили сжимать файлы самостоятельно и поштучно, то можно настраивать кеширование для распакованных файлов. Удалять nginx будет самостоятельно, следить нам не надо, только выставить нужные сроки инвалидации
  8. Загрузка файлов.
    При наличии множества шард нам придётся реализовать загрузку на выбранную шарду
    Механизм похож на скачивание. Сначала определить на какую шарду поместить хотим, затем залить.
    Можно генерировать служебное имя файла заранее, тогда адрес загрузки вместе с нужным именем шарды отдавать сразу с формой клиенту и он при отправке будет грузить сразу в нужное место.
    Но можно и изначально грузить на сервер приложения и переносить на нужную шарду.
  9. Не вижу проблемы хранения картинок в виде файлов.

Что касается простоты.
Да, хранить все в одной БД — проще.
Это пока единственный аргумент "за".
Но для случаев, когда "проще" имеет смысл — о масштабировании проще забыть.
Или то, или другое.


Более конкретные рецепты реализации зависят от того что именно пишется.
Какие задачи выполняет приложение и т.д.
Ну и для почитать http://ruhighload.com/server

Спасибо за ссылку. Действительно все вместе и по полочкам. Много интересного.

Да, хранить все в одной БД — проще.
Это пока единственный аргумент «за».
Но для случаев, когда «проще» имеет смысл — о масштабировании проще забыть.
Или то, или другое.


У меня не в одной БД. Структура такая, каждой компании выделяются аккаунт, каждый сотрудник компании может войти в этот аккаунт (со своими правами конечно). Каждому аккаунту выделяется своя рабочая база данных, файловая база данных, база данных для хранения логов и т.д. Есть база данных со структурой, где хранится у какой компании какая БД и на каком сервере она находится. При авторизации пользователя из базы данных со структурой получаем адресацию хранения его БД, и после он работает уже только с ними.
На серверах с БД есть скрипты и исходник БД с типовой конфигурацией. При регистрации происходит копирование типовой БД и запись в базу структуры ее адреса нахождения.
Масштабируемость неограниченная получается.

По бекапам. Рабочую базу все равно надо бекапить. Бекапить заодно и его файловую базу в данном случае не сложно, фактически один механизм. Ничего дополнительно городить не надо.
У меня реализован механизм управления бекапом от пользователя, он сам указывает в какие дни, в какой временной диапазон и какие базы бекапить, за сколько дней хранить копии и т.п. Технически — обновляется cron на нужном сервере в соответствии с планом бекапов. На сервере для бекапов работает скрипт, который просматриает по ftp папочки на этих серверах с определенной периодичностью и тянет к себе файлы, удаляет оригиналы бекапов освобождая место.
Масштабируемость неограниченная получается.

… и что случится, когда мощности одного сервера перестанет хватать для поддержки аккаунта?

Такое сложно представить в SaaS концепции. Но если вдруг будет такой совсем «жирный» клиент. Я ему просто выделю отдельное оборудование. Но вообще обычно в этом случае «коробочные версии» делают.
Такое сложно представить в SaaS концепции.

Да ладно, легко и непринужденно.


Но если вдруг будет такой совсем «жирный» клиент. Я ему просто выделю отдельное оборудование.

… а когда и этого "отдельного оборудования" перестанет хватать?

… а когда и этого «отдельного оборудования» перестанет хватать?


Тогда буду решать вопрос в индивидуальном порядке

Вот и нет никакой "неограниченной масштабируемости".

У меня не в одной БД.

Подразумевалось «все связанные данные и ресурсы в одной БД»

Если у вас пользователи не имеют связей между собой, то естественно БД может быть больше одной
По этому вопросу еще озвучу свои мысли.

Компрессия/декомпрессия файлов не относится к общему случаю.
Объём диска обычно дешевле процессорного времени, если вы не файл/фото хостинг
Поэтому сжимать изначально — нет смысла, поскольку это относится к оптимизации.


Изначально файл грузится в оригинальном виде. Потом в фоновом режиме проверяется имеет ли смысл вообще его трогать. Для проверки и сжатия можно выделить виртуалку с одним ядром (ограничим влияние на остальные ресурсы), тут нам не важно чтобы все летало, т.к. работа в фоне. Если его можно сжать неплохо то имеет, если сжатие кпеечное, то конечно нет.
И сжимать только маленькие файлы, извлечение которых процесс очень быстрый и не заметен для пользователя.
В общем на мой взгляд тут должен быть вопрос целесообразности. Как показывает практика, в процессе работы офиса в основном прикладывается куча небольших файлов (xls, doc, pdf) они неплохо сжимаются, имеют небольшой объем и их отдача из сжатого вида получается весьма быстрой.
Посмотрим конечно что будет еще при возрастании объемов, если что данный механизм всегда можно отключить и далее хранить в оригинальном виде все.
Sign up to leave a comment.

Articles