Паттерны

Работа с большими файлами

Узнайте, как работать с большими файлами на интервью по System Design

📁 Работа с большими файлами (такими как видео, изображения и документы) требует особого подхода в распределенных системах. Вместо того чтобы пропускать гигабайты данных через свои серверы, этот паттерн предлагает использовать предподписанный URL (presigned URL), чтобы клиенты могли загружать файлы напрямую в объектное хранилище и скачивать их с CDN. Дополнительно мы получаем возможность возобновления загрузок, параллельную передачу данных и отслеживание прогресса - все то, что отличает производственные системы от пет-проектов.

Проблема

Если вы готовились к интервью по System Design, вы уже знаете, что большие файлы нужно хранить не в базе данных, а в объектном хранилище, таком как S3. Это позволяет масштабировать хранение независимо от вычислений и сохраняет хорошую производительность базы данных.

Почему именно объектное хранилище? Базы данных отлично работают со структурированными данными и сложными запросами, но плохо подходят для больших бинарных объектов. Файл размером 100 МБ, сохраненный как BLOB, ухудшает производительность запросов, увеличивает время бэкапов и усложняет репликацию. Объектные хранилища (такие как S3) созданы именно для этого: они предлагают практически неограниченную емкость, надежность "11 девяток" (99.999999999%) и оплату за каждый объект. Простое практическое правило: если размер файла превышает 10 МБ и нам не нужны SQL-запросы по его содержимому, его стоит хранить в объектном хранилище.

Хотя использование объектного хранилища решает проблему хранения, оно не устраняет проблему передачи данных. При стандартном подходе данные файла проходят через серверы приложения. Клиент загружает видео на 2 ГБ, API-сервер его принимает и затем перенаправляет в хранилище. При скачивании происходит то же самое: хранилище отправляет данные на API-сервер, а тот передает их клиенту. Для небольших файлов это работает, но по мере роста размера файлов такой подход становится неэффективным.

Сервер как прокси

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

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

Если загрузка файла на 25 ГБ падает на 99%, все приходится начинать заново. Мы теряем видимость прогресса, потому что передача больше не идет через наши серверы. В базе данных у файла может стоять статус "pending", хотя S3 уже полностью получил объект. Или не получил, и без дополнительной проверки мы не поймем, что именно произошло.

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

Работа с большими файлами в распределенных системах - задача не из легких. Так какие паттерны могут нам помочь?

Задачи, где важна работа с большими файлами

Перейдите на Premium, чтобы продолжить

Разблокируйте доступ к этой статье и всем остальным материалам с NowInterview Premium

Перейти на Premium