Кейс: URL shortener

↑ 8.4 Backend System Design · ← Предыдущая · → Следующая

Обязательно~3 мин чтенияУровень: senior

Зачем это на собесе

Классическая задача. Показывает генерацию ключей, кэш и оценку нагрузки.

Объяснение

Требования: создать короткую ссылку, редирект по ней, опционально свой алиас, срок жизни, статистика кликов. Нефункциональные: редирект быстро (< 50 мс), высокая доступность, чтения ≫ записей (100:1), данные хранятся годами.

Оценка: 100 млн ссылок в месяц → ~40 записей/с, ~4 000 RPS чтений (пик 20 000). Хранение ≈ 3 ТБ за 5 лет.

API:

POST /links   { "url": "https://…", "alias": "my-link", "ttl": "30d" }  → 201 { "short": "https://sho.rt/aB3xY9" }
GET  /{code}  → 301/302 Location: https://…

Генерация кода (7 символов Base62 ≈ 62⁷ ≈ 3,5 трлн комбинаций):

СпособПлюсыМинусы
Хэш URL (MD5 → первые 7 символов)одинаковый URL — одинаковый кодколлизии, нужна проверка
Счётчик + Base62без коллизий, короткопредсказуемо; счётчик — единая точка (диапазоны на инстанс)
Случайный ID + проверка уникальностинепредсказуемоповторные попытки при коллизии
Заранее сгенерированные ключи (Key Generation Service)быстро, без коллизийотдельный сервис

Схема:

flowchart LR
  C[Клиент] --> LB[Балансировщик] --> A[Stateless API]
  A --> R[(Redis кэш)]
  A --> DB[(БД: code → url)]
  A -. клики .-> KKafka --> CH[(ClickHouse)]
  • Хранилище: key-value (DynamoDB/Cassandra) или PostgreSQL с индексом по code; шардирование по хэшу кода.
  • Кэш Redis для горячих кодов (LRU): попадание > 90%.
  • 301 (постоянный) кэшируется браузером и снижает нагрузку, но теряет статистику; 302 — точнее считает клики.
  • Клики отправляются асинхронно в Kafka → агрегация в ClickHouse.
  • Удаление просроченных ссылок — фоновая задача/TTL.

Нюансы и подводные камни

  • Защита от злоупотреблений: фишинг-ссылки, rate limiting, проверка URL.
  • Предсказуемые коды позволяют перебирать чужие ссылки.
  • Коллизии хэша при высокой нагрузке.
  • Единая точка отказа в генераторе счётчика.
  • Кэширование негативных результатов (несуществующие коды).

Практика

  1. Реализуйте генерацию Base62 из диапазонов счётчика.
  2. Оцените hit-rate кэша на реальном распределении запросов.
  3. Опишите деградацию при падении Redis и БД.

Вопросы с ответами

Связанные темы