Все проекты

Ads Platform

B2B видеореклама VAST/VMAP. 100M запросов/день. CPM-аукцион в реальном времени. Java + Go.

100M запросов/день< 10ms аукционСнижение нагрузки на ClickHouse в 1000x

Бизнес-задача

Платформа связывает рекламодателей и паблишеров. Рекламодатель задаёт максимальный CPM и бюджет, паблишер — минимальный CPM. Платформа проводит аукцион, показывает рекламу, списывает деньги, начисляет выплаты — всё в реальном времени.

Ключевая задача

Запрос на рекламу должен вернуть VAST за < 50ms, но при этом нужно: проверить баланс, провести аукцион по CPM, отфильтровать по гео/формату/тегам, сгенерировать XML с трекинг-пикселями. Решение: разделение на два сервиса. Java — админка, управление кампаниями, финансы. Go — горячий путь: аукцион, отдача VAST, приём событий. Горячие данные в Redis, Go читает только оттуда.

Архитектура

┌─────────────────┐     ┌─────────────────┐
│  Java Backend   │────▶│    PostgreSQL   │
│  (админка, API) │     │  (users, camps) │
└────────┬────────┘     └─────────────────┘
         │ sync
    ┌────▼────┐
    │  Redis  │
    │ (cache) │
    └────┬────┘
         │ read-only
┌────────▼────────┐     ┌─────────────────┐
│   Go Service    │────▶│      NATS       │
│ (аукцион, VAST) │     │   (events)      │
└────────┬────────┘     └────────┬────────┘
         │                       │ batch
         │              ┌────────▼────────┐
         └─────────────▶│   ClickHouse    │
                        │  (analytics)    │
                        └─────────────────┘

Почему два сервиса

Админка и показ рекламы — разные паттерны нагрузки. Java (Spring Boot) для админки — ORM, Security, сложная бизнес-логика. Go (fasthttp) для горячего пути — минимум аллокаций, горутины, < 10ms на запрос. Независимое масштабирование: Go-поды автоскейлятся по CPU.

Аукцион второй цены (Redis)

Активные кампании индексированы в Redis Sorted Set по CPM. При запросе: пересечение множеств, сортировка по ставке, проверка баланса. Победитель платит ставку второго места + 1 цент.
  • adv:active — множество активных кампаний
  • adv:cpm — отсортированное множество по ставке
  • adv:{id}:tags — теги кампании
  • balance:{member} — текущий баланс (атомарные операции)

Финансовый учёт: горячий кошелёк + холодный журнал

Redis хранит текущий баланс — атомарный DECRBY при каждом показе, проверка за O(1). PostgreSQL хранит append-only журнал транзакций. Фоновая задача сверяет балансы Redis с суммой событий в PostgreSQL.

Пакетная обработка событий

100M запросов/день = 100M INSERT-ов. ClickHouse любит пакеты. Go публикует события в NATS без ожидания. Отдельный потребитель накапливает буфер (1000 событий или 2 сек таймаут), затем пакетный INSERT. Нагрузка на ClickHouse снижена в 1000 раз.

Технологии

Java Backend

Java 21Spring Boot 3Spring Data JPASpring SecurityLiquibase

Go Service

Go 1.25fasthttpgo-redisclickhouse-goNATSMaxMind GeoIP2

Data

PostgreSQLClickHouseRedisNATS JetStreamS3

Infra

KubernetesArgoCDPrometheusNGINX Ingress

Наша роль

  • Спроектировали двухсервисную архитектуру (админка vs горячий путь)
  • Реализовали CPM-аукцион на Redis с задержкой < 10ms
  • Реализовали гибридную финансовую модель с фоновой сверкой
  • Настроили GitOps-пайплайн (ArgoCD)
1 слот свободен
Написать