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

Начнём с требований к хранилищу, которые учитывают специфику видеоконтента и архитектуру RUTUBE (кстати, подробнее о ней рассказывается в отдельной статье):
Надёжность — базовое требование к любому хранилищу.
Низкая стоимость хранения контента — имеет большое значение, когда речь идёт о таких объемах контента, как у нас.
Высокое быстродействие — так как обращение к хранилищу может внести существенный вклад в скорость отклика сервиса, а мы хотим, чтобы пользователь не ощущал задержек, когда выбирает просмотр интересного ему видеофайла.
Горизонтальная масштабируемость тоже очень важна на таком объеме хранения. Так как объемы заливаемого видео постоянно растут, нам нужно регулярно вводить в эксплуатацию новые серверы. Когда вы систематически запускаете по 200-250 серверов файлового хранилища за раз, нужно делать это так, чтобы это занимало минимальное количество времени и требовалось как можно меньше ручного труда инженеров.
Далее подробно разберём, как мы обеспечиваем каждый из пунктов, с фокусом на эффективность хранения.
Эта статья написана по мотивам доклада Эдгара Воскресенского, SRE RUTUBE на конференции Saint HighLoad++.
RUTUBE — видеохостинг, а не банк. Мы не закладываем требование стопроцентной сохранности данных при любых катаклизмах, которое подразумевает обязательно три реплики данных. Мы минимизируем риски потери пользовательского видео, используем две реплики, делаем резервные копии и на практике имели возможность убедиться, что этого достаточно. Когда мы на 10 часов потеряли целиком дата-центр с хранилищем видео, ни один из дисков реплик не вышел из строя и никакие пользовательские данные не были утрачены. Несмотря на очень большие количества жёстких дисков и серверов, в среднем мы теряем примерно от 3 до 10 дисков в месяц, что совсем немного. Поэтому для нас держать три реплики не целесообразно с точки зрения стоимости владения — цена вырастет кардинально.
Серверы видеохранилища
Какие серверы мы используем для файлового хранилища, как балансируем стоимость хранения и производительность на уровне железа?
HDD vs SSD
Как только появились SSD диски, аналитики начали «хоронить» HDD. Первые успехи в массовом производстве и, как следствие, удешевление SSD давали ощущение, что пройдет несколько лет и жесткие диски вымрут, останутся только SSD. Однако мы все всё ещё в той ситуации, когда стоимость хранения на SSD в 10 и более раз превышает стоимость хранения на традиционных жёстких дисках. Развиваются не только SSD, но и в HDD внедряют новые технологии.

Если нужно хранить очень большие объемы данных и при этом нет критичных требований к скорости доступа, конкурентов по стоимости у HDD нет. Типичная комплектация сервера хранилища RUTUBE выглядит следующим образом:
Chassis |
4U |
CPU |
Intel(R) Xeon(R) Gold xxxx Series |
RAM |
DDR4 ECC/REG не менее 128Gb и не менее 3200МГц |
Storage |
2x SSD минимум 480Gb под ОС (Hardware RAID), не менее 36х HDD SATA 16Tb (JBOD) |
Hard Disk Controller |
не менее 1х контроллер LSI/Broadcom SATA HBA (JBOD) |
Network |
2x Mellanox 2 port SFP+, 10GbE |
Мы отказались от RAID-массивов и любых СХД на серверах видеохранилища. Используем железо любого вендора, но предъявляем два важных требования:
возможность полной настройки, от BIOS и IPMI до установки ОС, с помощью утилит, таких как Redfish, для полностью автоматического ввода в эксплуатацию любого количества серверов;
плотность жестких дисков в сервере не менее 36, а по возможности больше.
Объясню на примере, какое значение на наших объемах имеет плотность дисков в сервере. Рассмотрим современный хороший сервер Supermicro, ёмкость которого 90 жестких дисков на 4 юнита.

Если использовать диски по 18 Тбайт, то ёмкость одного сервера будет 1,62 Пбайт.
Соответственно, в обычную стойку на 10 серверов войдет 16 Пбайт. Это почти в 2,5 раза большая плотность по сравнению с более старой конфигураций на 36 дисков, где максимально в одну стойку можно впихнуть 6,5 Пбайт.

Мы сейчас используем в основном диски на 18 Тбайт, но Seagate уже выпустил в продажу 36-терабайтные серверные диски. С ними в одну стойку уже можно уместить 32 Пбайта — то есть всё видеохранилище, накопленное RUTUBE к лету 2025-го, без учёта репликации можно уместить всего в 15 стоек! А раньше это было бы несколько машинных залов.
Почему мы здесь вообще считаем стойки? Во-первых, их аренда тоже стоит денег: средняя цена по рынку где-то 140 тысяч рублей в месяц. В нашем примере при хранении 16 Пбайт на серверах по 90 дисков вместо 36 экономия получится 210 тысяч рублей в месяц. Не столь заметно для большой компании, но это ещё не всё.
Во-вторых, давайте рассчитаем стоимость железа на примере тех же серверов Supermicro 12-го поколения. С одной стороны, сама платформа на 90 дисков почти в два раза дороже, с другой — требуется 10 серверов, а не 25 (для ориентира используем цены европейского поставщика, потому что в России логистические факторы вносят существенные коррективы).
Цена за 1 сервер |
Нужно серверов на 16 Пбайт |
Стоимость итого |
|
Storage SuperServer |
10 812 € |
10 |
108 120 € |
Storage SuperServer SSG-640P-E1CR36H |
5 795 € |
25 |
144 875 € |
Даже при более дорогой платформе разница на эту ёмкость составит 34% или 36755 €.
Ниже расчёт для полной комплектации серверов со всем железом на платформе одного поколения — здесь разница составляет 21% и больше 128870 €.

Серверное ПО
На серверах видеохранилища RUTUBE стоит:
Rocky Linux — дистрибутив, который появился как форк Red Hat Enterprise Linux и должен быть на 100% с ним совместимым.
Angie — nginx-совместимый форк, который имеет дополнительные плюшки, например, в виде возможности получения конфигурации сервера и статистики по API и большого набора уже собранных сторонних модулей.
Модуль Kaltura для адаптивного видеостриминга.
FileHeap — самописное ПО, о котором поговорим дальше.
Указанные характеристики позволяют нам не испытывать каких-либо проблем с производительностью на серверах видеохранилища. Пиковый трафик отдачи RUTUBE составляет примерно 7 Тбит/с, однако он распределяется по CDN (подробнее о CDN RUTUBE читайте в отдельной статье), а нагрузка по сети на один сервер весьма разумная.
Ниже пример графика скорости отдачи непосредственно из файлового хранилища, для наглядности с достаточно слабого старого сервера.

Нагрузка на процессор (старого сервера с однопроцессорной конфигурацией) в пике составляет 40%, обычно меньше.

FileHeap
RUTUBE создавался в 2006 году. Тогда ещё не существовало хороших общепринятых готовых решений для файлового хранилища, Amazon S3 и Ceph появились позже. Поэтому видеохранилище создавалось логичным и доступным тогда способом — с нуля самостоятельно, ориентируясь на основную задачу, то есть хранение видео для видеохостинга.

Наше ПО управления хранилищем называется FileHeap. Оно написано на Python, для хранения всех объектов используется RabbitMQ и PostgreSQL, для кеша — Redis. Это хранилище разработано специально для хранения видео, оптимизировано под него и ни для чего другого не используется.
Рассмотрим основные задачи FileHeap.
Управление хранилищем контента — стандартный необходимый набор админских функций: добавлять и удалять серверы, регулировать количество репликаций, добавлять и удалять пользователей и так далее.
Загрузка/удаление контента в хранилище. Основная функция для любого файлового хранилища — загрузка файлов и их удаление.
Получение сведений о контенте в хранилище — его хэш-суммы, даты и всей информации о файле, которая нам необходима.
Раздача контента клиентам. FileHeap на самом деле ничего не раздаёт пользователям, он лишь сообщает сервису балансировки, где находится видео, на каком сервере его необходимо найти: в основном видеохранилище или в реплике на CDN-серверах. На основании чего уже балансер генерирует манифест для потока и отдаёт его на клиент.
Актуализация storage — постоянный процесс поддержания необходимого количества активных актуальных реплик (напомним, у нас их две).
Валидация storage — постоянный процесс проверки на ошибки доступности жестких дисков непосредственно на сервере. Если что-то выходит из строя, FileHeap сразу же узнаёт об этом через RabbitMQ, автоматически запускается система создания активных реплик на других дисках или серверах.
Балансировка storage — процесс перемещения реплик по серверам хранения для равномерного распределения нагрузки на них. Обычно мы добавляем сервера большими пачками, например, по 200 новых за раз. Чтобы не влиять на производительность хранилища, переносим данные в фоновом режиме, когда нагрузка на существующие серверы минимальна. Так постепенно контент размазывается по серверам, что позволяет равномерно балансировать нагрузку между ними.
Check online storage — процесс проверки реплики на доступность. Сервер хранилища может даже быть жив, но потерять сетевую связность с CDN — мы это тут же увидим на мониторинге, а балансировщик будет создавать манифест с живыми серверами, чтобы пользователи ничего не заметили.
Ниже схема взаимодействия видеосервисов. В рамках этой статьи не будем углубляться во все элементы (напишите в комментариях, что стоит раскрыть подробнее в следующих материалах), здесь нас интересует хранилище, в том числе то, как видео в него попадает.

Как видео попадает в видеохранилище
Пользователь может залить видео практически в любом формате и любом качестве. Мы поддерживаем upload для: MP4, AVI, WMV, MOV, FLV, MPEG-1, MPEG-2, MPEG-4, MPG, MPEGPS, 3GPP, WebM, DNxHR, ProRes, CineForm, HEVC (H.265). Загруженное видео нам нужно преобразовать в формат, который мы потом сможем показать на всём многообразии пользовательских устройств. Соответственно, перед тем как положить видео в основное видеохранилище, нужно его перекодировать (у нас основной кодек H.264) и нарезать в разные качества для адаптивного стриминга (поддерживаем от 144p до 8К).
Разберём этот процесс по шагам.

Данные от пользователя загружаются на upload-серверы, которые представляют из себя, по сути дела, просто серверы временного хранения, но с очень быстрыми NVMe-дисками. Их не очень много и их основная цель — максимально быстро получить контент от пользователя и начать обработку.
Как только видео заливается на upload, оно отдаётся на сервер транскодирования, который у нас называется WatchDuck.
Каждое видео нарезается во все поддерживаемые качества (ниже исходного) и в нужном кодеке отправляется в FileHeap.
FileHeap раскладывает все экземпляры видео во всех качествах по двум серверам видеохранения обязательно в двух разных дата-центрах.
Особенности хранения очень большого количества файлов
Как мы видим, видео хранится во многих качествах, то есть 400 млн единиц контента превращается примерно в 2 миллиарда объектов хранилища. Это может стать проблемой, если не учесть одну особенность устройства файловых систем, про которую нередко забывают в современной разработке. Возможно, потому что люди всё реже работают на низком уровне, а всё чаще оперируют абстракциями типа контейнеров.
Представьте: проект тестировали на dev, всё было хорошо, всё работало быстро. Отдали на прод, и через какое-то время производительность очень деградировала или и вовсе проект перестал работать. Что случилось?
Дело в том, что для хранения всех, скажем, пользовательских картинок разработчикам выдали один бакет. Однако в большинстве случаев, в частности в случае популярной реализации S3 MinIO, бакет — это просто отдельная папка в файловой системе (больше о работе с MinIO читайте в другой статье из нашего блога).

На 10-20 тысяч файлов — а dev за эти рамки обычно не выходит — всё замечательно работает. Далее проект выходит в продакшен, несколько недель нормально функционирует, бакет заполняется, и начинается резкая деградация скорости ответа MinIO. По достижении примерно 100 тысяч файлов (зависит от файловой системы на серверах) система полностью выходит из строя и уже не отдает ничего. Причем быстро это исправить проблематично.
Чтобы предотвратить подобное поведение, давно придумали хеш-структурированное хранение. Работает следующим образом: берётся, например, хеш-сумма файлов (мы вместо хеш-суммы используем UUID), создаются папки и подпапки по значениям последних символов хеш-суммы, файлы раскладываются в соответствующие подпапки — ни одна директория не переполняется.

Глубина вложенности может быть 2 или 3, при этом используется 4 или 6 последних символов хеш-сумм (или UUID, как в нашем случае). При вложенности 2 получается, что будет создано (16*16) ² = 65536 поддиректорий. При вложенности 3 получится уже ≈16 млн поддиректорий.
Для наглядности рассчитаем подходящую глубину вложенности в случае видеохранилища RUTUBE. На диски по 18/36 Тбайт, которые мы используем, помещается порядка 100 000 файлов — видео тяжелые и в среднем занимают несколько сотен мегабайт. При глубине вложенности 2 получится по 5-10 файлов в директории — это нам подходит. Если сделать глубину вложенности 3, то можно разложить 1 млрд файлов (примерно по 60 файлов в каждой директории). Таким образом можно в тот же самый бакет заливать сколько угодно файлов, просто регулируя глубину вложенности по папкам.
Хеш-структурированное хранение даёт не столько ускорение, сколько просто возможность создать рабочую масштабируемую конфигурацию и хранить миллиарды файлов без потери производительности. Потому что иначе, если в одном каталоге будет слишком много объектов, файловая система в Unix-системах будет отвечать очень медленно вплоть до полной невозможности с ней работать.
Раздача видеоконтента
Контент, который мы складываем в видеохранилище, мы храним не просто так, а чтобы наши зрители в любой момент могли посмотреть что-то интересное для себя — сделать это без задержки и с любого устройства. За минимизацию задержки отвечает двухуровневый CDN, где на первом уровне кешируется холодный контент, а на втором — расположенном как можно ближе к зрителям — горячий, то есть наиболее популярный в данном регионе.

А для того, чтобы видео воспроизводилось на самых разных устройствах — от компьютеров до бюджетных телефонов и Smart TV — мы как раз и перекодируем исходное видео и используем алгоритмы адаптивного стриминга.
Существует два основных протокола адаптивного видеостриминга: HLS (HTTP Live Streaming, разработан Apple в 2009) и DASH (Dynamic Adaptive Streaming over HTTP, разработан рабочей группой MPEG в 2011 году). Они отличаются способами организации манифеста, но базово устроены похоже и вы точно сталкивались с их работой. Именно они отвечают за то, чтобы, если у пользователя ухудшилось качество связи, воспроизведение не прервалось, а просто уменьшить разрешение видео.
Протокол адаптивного стриминга позволяет переключаться между фрагментами подходящего разрешение. Однако, естественно, заранее заготовить всевозможное разбиение на фрагменты невозможно и нерационально, поэтому используется переупаковка на лету.
Чтобы на лету нарезать нужные фрагменты, мы используем nginx-модуль vod от компании Kaltura. Он читает исходный mp4-файл и динамически его сегментирует в нужный протокол: HLS (.m3u8 + .ts) или DASH (.mpd + .mp4).
Ниже короткие примеры конфигурации:
location /hls-vod/ {
alias /media/;
vod hls;
vod_bootstrap_segment_durations 2000;
vod_bootstrap_segment_durations 2000;
vod_segment_duration 4000;
vod_base_url "$video_id.mp4/";
vod_mode local;
hls_metadata_cache 16m;
vod_align_segments_to_key_frames on;
vod_hls_segment_file_name_prefix "segment";
vod_manifest_segment_durations_mode accurate;
}
location /dash-vod/ {
alias /media/;
vod dash;
vod_bootstrap_segment_durations 2000;
vod_bootstrap_segment_durations 2000;
vod_segment_duration 4000;
vod_align_segments_to_key_frames on;
vod_manifest_duration_policy min;
vod_dash_manifest_format segmenttemplate;
vod_dash_profiles urn:mpeg:dash:profile isoff-live:2011;
vod_base_url "$video_id.mp4/";
}
Здесь созданы две локации, где в качестве root мы указываем одну и ту же папку с одними и теми же видеофайлами. При обращении к одной пользователь будет получать манифест DASH, к другой — HLS. Из основных параметров — длина чанков, и для разных форматов стриминга она может быть задана по-разному.
Получается, что с одним сервером хранения может работать два плеера. Выбор между DASH и HLS зависит от того, что поддерживает устройство пользователя и что в данном случае будет эффективнее.
Пример запроса от плеера за HLS:
/hls-vod/0x5000c500c32ab248/77/ec/a8ae0fb363484dc180705b8a5dbc77ec.mp4/index.m3u8
Пример запроса от плеера за DASH:
/dash-vod/0x5000c500c32ab248/77/ec/a8ae0fb363484dc180705b8a5dbc77ec.mp4/manifest.mpd
А ещё vod-модуль позволяет на лету генерировать превью (thumbnails) — то есть картинку из видеофайла как стоп-кадр по временной метке в миллисекундах. Зачем это нужно? Во-первых, для перемотки по таймлайну, чтобы пользователь на миниатюрах видел, куда перетаскивает курсор. Во-вторых, для создания обложек. Авторы, которые заливают видео на RUTUBE, могут загрузить свою обложку, а могут использовать любой стоп-кадр, который и будет показываться на главной странице.
Надо заметить, что подход переупаковки на лету, кроме того что помогает экономить место в хранилище и обеспечивает скорость доступа к видео, еще и не вычислительно затратный. Единственную нагрузку создаёт генерация превью, нарезка чанков фактически не использует CPU, потому что это просто сегментирование MP4, никакой сложной обработки видео для этого не требуется.

Выше на графике скорость раздачи со всех вместе взятых серверов файлового хранилища. Пик нагрузки составляет ≈525 Гбит/с при общем трафике нашей платформы около 7Тбит/с. Это значит, что большая часть раздачи происходит с CDN-серверов, из хранилища забирается только незакешированое по CDN видео.
Это как раз и есть одна их главных особенностей хранилища в видеосервисе. Когда новое классное видео только появляется на платформе, его много смотрят и соответственно оно отдаётся с горячих CDN. Однако через какое-то время его уже смотрят единицы раз — с CDN оно вымывается, остаётся в основном видеохранилище, но так как интерес к нему уже не очень большой, то это не генерирует большую нагрузку. Не для всех видов контента, но для многих категорий деление на горячий и холодный контент ярко выражено.

Также для экспериментов и резервного копирования мы используем S3 у разных партнеров. Но, как показала практика, производительность S3 в холодной конфигурации оставляет желать лучшего. Мало у кого из партнеров её в принципе достаточно для того, чтобы раздавать видео. В некоторых случаях, максимум, на что можно рассчитывать, это положить бэкап и забыть. Всё остальное — непозволительная роскошь, использовать что-либо кроме холодной конфигурации слишком дорого. Поэтому мы и остановились на использование собственных обычных серверов без СХД и RAID-массивов.
Итоги
Спроектированная еще в 2006 году система хранения видео RUTUBE, конечно, многократно дорабатывалась, в неё добавлялись новые функциональные элементы, но на уровне базовой архитектуры она сохранила свою простоту, которая сейчас позволяет нам легко масштабироваться под любые нагрузки.
Подход, описанный в этой статье, обеспечивает:
Производительность, которая позволяет обрабатывать миллионы запросов без деградации скорости.
Отказоустойчивость — данные дублируются на уровне целых серверов и дата-центров, а не отдельных дисков. Отказ целого дата-центра не приводит к потере данных.
Масштабируемость — новые серверы и диски легко конфигурируются и автоматически раскатываются по системе управляющей хранилищем, что позволяет на лету перестраивать топологию и гибко масштабироваться под растущие нагрузки.
Гибкость и полный контроль — можно настраивать репликацию под конкретные требования и ситуацию.
Оптимизацию стоимости хранения, благодаря контролю всех слоёв.
Поэтому, если перед вами сейчас стоит задача проектирования хранилища для большого количества тяжелых данных и вы уделяете большое внимание стоимости хранения, то, возможно, готовые сторонние решения для вас тоже неоптимальны и какие-то из наших подходов окажутся вам полезны.
Подписывайтесь на этот блог и канал Смотри за IT, если хотите знать больше о создании медиасервисов: в них инженеры Цифровых активов «Газпром-Медиа Холдинга» таких, как PREMIER, RUTUBE, Yappy делятся своим опытом и тонкостями разработки видеоплатформ.
И увидимся на следующей конференции HighLoad++ 6–7 ноября в Москве, где будет 10 потоков докладов обо всех аспектах разработки высокнагруженных систем. А инженеры RUTUBE поделятся опытом построения и эксплуатации ML в большом продакшене.
Комментарии (7)
outlingo
30.09.2025 10:30А энергопотребление стойки в которой 900 дисков не "ой-ой-ой"? А то там ведь под 20 киловатт в неудачный момент может быть, а потом эти киловатты надо еще и в охлаждение увести.
grucshetsky_aleksei
30.09.2025 10:30Уверен, тут большинство не переносят рутуб, но техническая сторона от этого интереснее не становится. Спасибо, что делитесь ❤️
Ilya_JOATMON
Словом у вас получается полезная емкость - половина от сырой. Довольно расточительно.