Хранилище объектов для веб-приложения

В настоящее время я работаю над сайтом, на котором пользователям должно быть предоставлено около 40 миллионов документов и изображений. Мне нужны предложения о том, какой метод является наиболее подходящим для хранения контента с учетом этих требований.

  • Система должна быть высокодоступной, масштабируемой и долговечной.
  • Файлы должны храниться постоянно, и пользователи должны иметь возможность изменять их.
  • Из-за клиентских ограничений сторонние поставщики хранилищ объектов, такие как Amazon S3 и CDN, не подходят.
  • Размер файла содержимого может варьироваться от 1 МБ до 30 МБ. (Однако около 90% файлов будет меньше 2 МБ)
  • Задержка поиска контента не является большой проблемой. Поэтому индексация или кэширование не очень важны.

Я провел некоторое исследование и узнал о следующих решениях;

  • Хранение контента в виде BLOB в базах данных.
  • Использование GridFS для порции и хранения контента.
  • Хранение содержимого на файловом сервере в каталогах с использованием хэша и сохранение метаданных в базе данных.
  • Использование распределенной файловой системы, такой как GlusterFS или HDFS, и хранение метаданных файла в базе данных.

Сайт разработан с использованием PHP и Couchbase Community Edition используется в качестве базы данных.

Я был бы очень признателен за любой вклад.

Спасибо.

2 ответа

Решение

Я работал над подобной системой в течение последних двух лет, работа еще продолжается. Однако требования немного отличаются от ваших: изменения невозможны (я постараюсь объяснить, почему позже), размеры файлов падают в диапазоне от нескольких байтов до нескольких мегабайт, и, самое главное, дедупликация, которая должна быть реализована как на уровне документа и блока. Если два разных пользователя загружают один и тот же файл в хранилище, единственная копия файла должна быть сохранена. Также, если два разных файла частично пересекаются друг с другом, необходимо хранить единственную копию общей части этих файлов.

Но давайте сосредоточимся на ваших требованиях, поэтому дедупликация не так. Прежде всего, высокая доступность подразумевает репликацию. Вам придется хранить ваш файл в нескольких репликах (обычно в 2 или 3, но есть способы уменьшить четность данных) на независимых машинах, чтобы остаться в живых в случае смерти одного из серверов хранения в вашей бэкэнд-системе. Кроме того, принимая во внимание оценку объема данных, ясно, что все ваши данные просто не поместятся на одном сервере, поэтому вертикальное масштабирование невозможно, и вы должны рассмотреть возможность разделения. Наконец, вам нужно принять во внимание контроль параллелизма, чтобы избежать состязаний, когда два разных клиента пытаются одновременно записывать или обновлять одни и те же данные. Эта тема близка к концепции транзакций (я не имею в виду ACID буквально, но что-то близко). Итак, подведем итог: эти факты означают, что вы на самом деле ищете распределенную базу данных, предназначенную для хранения больших двоичных объектов.

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

  1. Выберите лидера, который будет общаться с другими партнерами и поддерживать глобальное состояние распределенной системы. Такой подход обеспечивает надежную согласованность и линеаризуемость. Основным недостатком является то, что в этом случае лидер становится единственной точкой отказа. Если лидер умирает, либо какой-либо наблюдатель должен назначить роль лидера одной из реплик (общий случай для master-slave репликации в мире СУБД), или оставшиеся одноранговые узлы должны выбрать новый (алгоритмы, такие как Paxos а также Raft предназначены для решения этой проблемы). Так или иначе, почти весь входящий системный трафик проходит через лидера. Это приводит к "горячим точкам" в бэкэнде: ситуации, когда затраты на ЦП и ввод-вывод неравномерно распределены по системе. Кстати, Raftсистемы с очень низкой производительностью записи (проверьте etcd а также consul ограничения, если вы заинтересованы).
  2. Избегайте глобального состояния вообще. Ослабить гарантии возможной последовательности. Отключить обновление файлов. Если кто-то хочет отредактировать файл, вам нужно сохранить его как новый файл. Используйте систему, которая организована как одноранговая сеть. Нет кластера в кластере, который бы полностью отслеживал систему, поэтому нет единой точки отказа. Это приводит к высокой скорости записи и хорошей горизонтальной масштабируемости.

Итак, теперь давайте обсудим варианты, которые вы нашли:

Хранение контента в виде BLOB в базах данных.

Я не думаю, что это хороший вариант для хранения файлов в традиционных RDBMS, потому что они обеспечивают оптимизацию для структурированных данных и строгую согласованность, и вам не нужно ни того, ни другого. Также у вас будут трудности с резервным копированием и масштабированием. Люди обычно не используют RDBMS таким образом.

Использование GridFS для порции и хранения контента.

Я не уверен, но похоже, что GridFS построен на вершине MongoDB. Опять же, это документно-ориентированная база данных, предназначенная для хранения JSON, а не BLOB. Также у MongoDB были проблемы с кластером в течение многих лет. MongoDB прошел тестирование Jepsen только в 2017 году. Это может означать, что кластер MongoDB еще не созрел. Сделайте тесты производительности и стресса, если вы идете по этому пути.

Хранение содержимого на файловом сервере в каталогах с использованием хэша и сохранение метаданных в базе данных.

Эта опция означает, что вам нужно разработать хранилище объектов самостоятельно. Рассмотрим все проблемы, которые я упомянул выше.

Использование распределенной файловой системы, такой как GlusterFS или HDFS, и хранение метаданных файла в базе данных.

Я не использовал ни одно из этих решений, но HDFS выглядит излишним, потому что вы зависите от стека Hadoop. Понятия не имею о производительности GlusterFS. Всегда учитывайте дизайн распределенных файловых систем. Если у них есть какие-то специальные "метаданные", рассматривайте их как единую точку отказа.

Наконец, мои мысли о решениях, которые могут соответствовать вашим потребностям:

  1. Эллиптика Это хранилище объектов мало известно за пределами российской части Интернета, но оно зрелое и стабильное, а производительность превосходна. Он был разработан в Яндексе (российская поисковая система), и на его основе построено множество сервисов Яндекса (таких как Disk, Mail, Music, Picture хостинг и т. Д.). Я использовал его в предыдущем проекте, это может занять некоторое время, чтобы ваши оперативники вошли в него, но оно того стоит, если вы согласны с GPL лицензия.
  2. Ceph. Это реальное хранилище объектов. Это также с открытым исходным кодом, но кажется, что только Red Hat люди знают, как развернуть и поддерживать его. Так что будьте готовы к вендору. Также я слышал, что у него слишком сложные настройки. Никогда не использовался в производстве, поэтому не знаю о производительности.
  3. Minio. Это S3-совместимое хранилище объектов, которое в данный момент активно разрабатывается. Никогда не использовал это в производстве, но это, кажется, хорошо разработано.

Вы также можете проверить вики- страницу с полным списком доступных решений.

И последний момент: я настоятельно рекомендую не использовать OpenStack Swift (есть много причин, почему, но, во-первых, Python просто не подходит для этих целей).

Один, вероятно, актуальный вопрос, ответ на который я не сразу вижу в вашем сообщении:

  • Как часто пользователи фактически "модифицируют" контент?

а также:

  • Когда и если они это сделают, насколько больно, если конкретный пользователь обслуживается "несвежим" контентом?

Лично (и, говоря "категорично"), я предпочитаю решать такие проблемы в два этапа: (1) идентификация объектов, которые должны быть сохранены - например, использование базы данных в качестве индекса; и (2) на самом деле их хранение, это задача, которую я хочу поручить "истинной файловой системе, которая в конце концов специализируется на таких вещах".

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

Другие вопросы по тегам