Я работал над аналогичной системой в течение последних двух лет, работа все еще продолжается. Однако требования немного отличаются от ваших: изменения невозможны (я постараюсь объяснить, почему позже), размеры файлов падают в диапазоне от нескольких байтов до нескольких мегабайт, и, самое главное, дедупликация, которая должна быть реализована как на уровне документа и блока. Если два разных пользователя загружают один и тот же файл в хранилище, единственная копия файла должна быть сохранена. Также, если два разных файла частично пересекаются друг с другом, необходимо хранить единственную копию общей части этих файлов.
Но давайте сосредоточимся на ваших требованиях, поэтому дедупликация не такова. Прежде всего, высокая доступность подразумевает репликацию . Вам придется хранить ваш файл в нескольких репликах (обычно 2 или 3, но есть способы уменьшить четность данных) на независимых машинах, чтобы остаться в живых в случае смерти одного из серверов хранения в вашем бэкэнде. Кроме того, принимая во внимание оценку объема данных, ясно, что все ваши данные просто не поместятся на одном сервере, поэтому вертикальное масштабирование невозможно, и вам необходимо учитывать разбиение . Наконец, вам необходимо принять во внимание контроль параллелизма , чтобы избежать состояния гонки, когда два разных клиента пытаются записать или обновить одни и те же данные одновременно. Эта тема близка к концепции транзакций (я не имею в виду ACID буквально, но что-то близко). Итак, подведем итог: эти факты означают, что вы на самом деле ищете распределенную базу данных, предназначенную для хранения больших двоичных объектов.
Одна из самых больших проблем в распределенных системах - это трудности с глобальным состоянием системы. Вкратце, есть два подхода:
- Выберите лидера, который будет общаться с другими коллегами и поддерживать глобальное состояние распределенной системы. Этот подход обеспечивает строгую согласованность и линеаризуемость гарантии. Основным недостатком является то, что в этом случае лидер становится единственной точкой отказа. Если лидер умирает, либо какой-либо наблюдатель должен назначить роль лидера одной из реплик (общий случай для репликации
master-slave
в мире РСУБД), либо оставшимся узлам необходимо выбрать новую (алгоритмы, такие как Paxos
и Raft
, предназначены для цель этой проблемы). В любом случае, почти весь входящий системный трафик проходит через лидера. Это приводит к «горячим точкам» в бэкенде: ситуации, когда затраты на ЦП и ввод-вывод неравномерно распределены по системе. Кстати, системы на Raft
имеют очень низкую пропускную способность записи (отметьте ограничения etcd
и consul
, если вам интересно).
- Избегайте глобального состояния вообще. Ослабить гарантии до Окончательная согласованность . Отключить обновление файлов. Если кто-то хочет отредактировать файл, вам нужно сохранить его как новый файл. Используйте систему, которая организована как одноранговая сеть. Нет кластера в кластере, который бы полностью отслеживал систему, поэтому нет единой точки отказа. Это приводит к высокой скорости записи и хорошей горизонтальной масштабируемости.
Итак, теперь давайте обсудим варианты, которые вы нашли:
Хранение содержимого в виде больших двоичных объектов в базах данных.
Я не думаю, что это хороший вариант для хранения файлов в традиционных RDBMS, потому что они обеспечивают оптимизацию для структурированных данных и высокую согласованность, и вам не нужно ни этого. Также у вас будут трудности с резервным копированием и масштабированием. Люди обычно не используют СУБД таким образом.
Использование GridFS для разделения и хранения контента.
Я не уверен, но похоже, что GridFS построен на вершине MongoDB. Опять же, это документно-ориентированная база данных, предназначенная для хранения JSON, а не BLOB. Также у MongoDB были проблемы с кластером в течение многих лет. MongoDB прошел тесты Jepsen только в 2017 году. Это может означать, что кластер MongoDB еще не созрел. Проведите тесты производительности и стресса, если вы идете этим путем.
Хранение содержимого на файловом сервере в каталогах с использованием хэша и хранение метаданных в базе данных.
Эта опция означает, что вам нужно разрабатывать хранилище объектов самостоятельно. Рассмотрим все проблемы, о которых я упоминал выше.
Использование распределенной файловой системы, такой как GlusterFS или HDFS, и сохранение метаданных файла в базе данных.
Я не использовал ни одно из этих решений, но HDFS выглядит излишним, потому что вы зависите от стека Hadoop. Понятия не имею о производительности GlusterFS. Всегда учитывайте дизайн распределенных файловых систем. Если у них есть какие-то специальные «метаданные», рассматривайте их как единую точку отказа.
Наконец, мои мысли о решениях, которые могут соответствовать вашим потребностям:
- Elliptics . Это хранилище объектов мало известно за пределами российской части Интернета, но оно зрелое и стабильное, а производительность превосходна. Он был разработан в Яндексе (российская поисковая система), и на его основе построено множество сервисов Яндекса (таких как Disk, Mail, Music, Picture хостинг и т. Д.). Я использовал его в предыдущем проекте, это может занять некоторое время, чтобы ваши оперативники вошли в него, но оно того стоит, если у вас все в порядке с
GPL
лицензией.
- Ceph . Это реальное хранилище объектов. Это также открытый исходный код, но, похоже, только 1071 человек знает, как его развернуть и поддерживать. Так что будьте готовы к вендору. Также я слышал, что у него слишком сложные настройки. Никогда не использовался в производстве, поэтому не знаю о производительности.
- Minio . Это S3-совместимое хранилище объектов, которое в данный момент активно разрабатывается. Никогда не использовал его в производстве, но, похоже, он хорошо продуман.
Вы также можете проверить страницу wiki с полным списком доступных решений.
И последний момент: я настоятельно рекомендую не использовать OpenStack Swift (есть много причин, почему, но, во-первых, Python просто не подходит для этих целей).