Медиа и хранилище: построй сервис загрузки-синка с чанками и дедупом
Практический проект: построй малый файловый сервис, что грузит байты прямо в объектное хранилище, режет файлы на адресуемые чанки ради delta-синка и дедупа, хранит метаданные отдельно и разрешает конфликты через цепочку версий — спина каждого дизайна юнита.
Прочитать, что «байты идут в объектное хранилище, а ты синкаешь дельты через адресуемые чанки», — не то же, что построить сервис, который это реально делает. Построй малый, но настоящий сервис загрузки-синка: байты никогда не касаются пути данных твоего сервера приложения, файлы хранятся дедуплицированными чанками, правка синкает лишь изменённые чанки, а две конфликтные правки обе выживают. Закончив, ты реализуешь в миниатюре спину, общую для YouTube, Drive и S3.
Этот проект делает юнит операционным. Ты отделишь путь управления от пути данных, реализуешь адресацию по содержимому и измеришь выигрыши delta-синка и дедупа, сохранишь метаданные отдельно от байт и докажешь, что цепочка версий предотвращает отказ молчаливой перезаписи, о котором предупреждает урок Drive.
Построй малый сервис загрузки-синка файлов, что хранит файлы адресуемыми по содержимому чанками в объектном хранилище (реальный S3/MinIO или локальная блоб-директория), держит метаданные в отдельной базе, синкает правки, передавая лишь изменённые чанки, дедуплицирует одинаковые чанки и разрешает конфликтные правки через цепочку версий — затем измерь выигрыши канала и хранилища, что даёт твой дизайн.
- Рабочий сервис, где загрузка хранит чанки в объектном хранилище и строку метаданных в БД, БЕЗ единого байта файла, хранимого в колонке БД или буферизованного целиком в памяти приложения — продемонстрируй это файлом в несколько сотен МБ.
- Демонстрация delta-синка: правка одного чанка крупного файла грузит лишь объём ~одного чанка байт, с залогированным счётом байт до/после, показывающим экономию на порядок vs полная перезагрузка.
- Демонстрация дедупа: тот же контент, сохранённый дважды, занимает один физический чанк (показано через счёт объектов блоб-хранилища и счётчик ссылок), а удаление одной ссылающейся версии не удаляет всё ещё ссылаемый чанк.
- Демонстрация конфликта: две правки от той же родительской версии обе выживают как конфликтные копии, с показанной цепочкой версий (указатели родителей) — перезапись last-writer-wins НЕ должна произойти.
- Краткий отчёт: раскол метаданные-vs-блоб, что ты выбрал, и почему, измеренные выигрыши delta-синка и дедупа до одной значащей цифры, и абзац о том, что изменилось бы для достижения S3-подобной долговечности (erasure coding по доменам отказа) на реальном масштабе.
- Замени фиксированный чанкинг на content-defined chunking (граница по rolling-hash) и продемонстрируй, что вставка байт в НАЧАЛО файла теперь ресинкает лишь затронутый чанк вместо каждого последующего — квантифицируй разницу.
- Добавь push-стиль уведомление об изменении: вместо опроса клиентами пусть сервер уведомляет подключённого клиента (WebSocket/long-poll), когда файл меняется, и клиент затем тянет лишь дифф метаданных и недостающие чанки.
- Добавь eventually-consistent счётчик (например, счёт скачиваний), реализованный логированием событий и асинхронной агрегацией, и контрастируй его пропускную с синхронным UPDATE на событие под нагрузочным тестом.
- Симулируй erasure coding: разбей чанк на k data + m parity фрагментов, храни их в отдельных «узлах» (директориях), удали до m фрагментов и реконструируй чанк из выживших — измеряя накладные по хранению vs 3-копийная репликация того же чанка.
- 01Какой ядровый структурный раскол проект заставляет тебя построить и почему?
- 02Как продемонстрировать delta-синк, дедуп и безопасность конфликтов и что масштабировало бы их до S3-подобной долговечности?
Этот проект превращает юнит медиа-хранилища в то, что ты построил. Ты поднимаешь объектное хранилище для байт и отдельную БД метаданных, затем реализуешь спину, общую для YouTube, Drive и S3: грузи байты напрямую в блоб-хранилище (никогда через буфер в памяти приложения или колонку БД), режь файлы на адресуемые по содержимому чанки и коммить версию метаданных со списком хешей чанков — чанки первыми, метаданные вторыми. Из этого одного механизма ты получаешь delta-синк (правь чанк, грузи лишь этот чанк и измерь экономию канала на порядок), дедупликацию (одинаковые чанки хранятся однажды со счётчиком ссылок) и целостность бесплатно. Ты делаешь систему безопасной цепочкой версий — каждая версия записывает родителя, так что две правки от той же базы обе выживают как конфликтные копии, а не молчаливая перезапись — и добавляешь multipart-стиль загрузку, чтобы передача крупного файла была надёжной. Поставка — не просто код, а измерение: выигрыши delta-синка и дедупа до одной значащей цифры и абзац о том, что потребовало бы достижение реальной S3-подобной долговечности (erasure coding по доменам отказа). Построй это однажды — и дизайны юнита перестают быть диаграммами и становятся мышечной памятью.
Что-то непонятно?
Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.