Сократитель ссылок (TinyURL)

Самая частая разминочная задача: спроектировать сервис коротких ссылок по фреймворку.

TinyURL — сервис, превращающий длинный URL в короткий код и редиректящий по нему; классическая read-heavy задача с упором на генерацию ключа и кэш.

Требования и масштаб

Функционально: создать короткую ссылку, перейти по ней, опционально аналитика. Нефункционально: высокая доступность, быстрый редирект (< 100 мс), read-heavy (переходов гораздо больше, чем созданий). Прикинем масштаб: 100M новых ссылок в месяц, чтения:запись ~100:1, значит редиректы — основная нагрузка.

Генерация короткого кода

ПодходПлюс/минус
Хэш длинного URL + срезПросто, но коллизии
Счётчик + base62Без коллизий, но предсказуемо/централизованно
Заранее сгенерированный пул ключейБыстро на запись, нужен генератор

base62 (a-z, A-Z, 0-9) даёт ~56 млрд комбинаций на 6 символов — с запасом. Счётчик через диапазоны (range allocation) на каждый инстанс снимает централизацию.

Высокоуровневая схема

Создание:  Клиент -> LB -> App -> БД(short -> long)
Редирект:  Клиент -> LB -> App -> [Cache] --промах--> БД -> 302

Данные простые — отображение short -> long по ключу, идеальный кейс для key-value хранилища. Горячие ссылки держим в кэше, поэтому подавляющее большинство редиректов не доходит до БД.

Как работает под капотом

Узкое место — редиректы, и их спасает кэш: распределение переходов длиннохвостое, малая доля ссылок собирает почти весь трафик, поэтому кэш-хит близок к 100%. БД нужна как источник истины и для холодных ссылок. Аналитику кликов лучше писать асинхронно через очередь, чтобы не замедлять сам редирект. Объём (3 ТБ за 5 лет, из прошлого раздела) умещается без обязательного шардирования, но его упоминают как точку роста.

Частые ошибки

  • Хэшировать без обработки коллизий.
  • Делать редирект через тяжёлый путь в БД без кэша.
  • Писать аналитику синхронно в горячем пути редиректа.

Итог

  • TinyURL — read-heavy: главное узкое место это редиректы, лечит кэш.
  • Короткий код — base62 от счётчика или хэш с разрешением коллизий.
  • Хранилище key-value (short -> long), аналитика — асинхронно.
Проверьте себя
1. Какое узкое место главное в сервисе коротких ссылок?
AСоздание ссылок
BРедиректы (чтения), которых на порядки больше
CУдаление ссылок
DРегистрация пользователей
2. Почему кэш так эффективен для редиректов TinyURL?
AКэш хранит все ссылки целиком
BРаспределение переходов длиннохвостое: малая доля ссылок даёт почти весь трафик
CРедиректы не используют БД вообще
DКэш ускоряет создание ссылок
3. Как лучше писать аналитику кликов, чтобы не замедлять редирект?
AСинхронно в том же запросе
BАсинхронно через очередь сообщений
CВообще не собирать
DВ оперативной памяти балансировщика