Обновлено: 8 апреля 2026 г. в 13:35

URL Shortener (TinyURL)

средний

Классический кейс про сокращатель ссылок: как выбрать длину короткого идентификатора, генерировать уникальные ID, кэшировать редиректы и масштабировать хранилище соответствий.

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

Глава полезна тем, что заставляет отдельно продумать путь записи и путь чтения: что кэшировать, где могут появиться горячие ключи и как не превратить генератор ID в новую точку отказа.

В интервью и архитектурных обсуждениях этот кейс быстро показывает, умеете ли вы видеть асимметрию чтения и записи, выделять настоящее узкое место и не усложнять решение раньше времени.

Control Plane

Фокус на governance-политиках, лимитах, маршрутизации и стабильности edge-поведения.

Data Path

Нужно держать предсказуемую latency и throughput при росте трафика и burst-нагрузке.

Failure Modes

Покрывайте fail-open/fail-close, деградацию и безопасный резервный сценарий при частичных отказах.

Ops Ready

Показывайте мониторинг saturation, retry storm и операционные защитные ограничения.

URL Shortener (TinyURL, bit.ly) — классическая задача по системному дизайну. Она кажется простой, потому что снаружи это всего лишь создание короткой ссылки и редирект по ней. Но внутри быстро появляются серьёзные вопросы: как генерировать компактные идентификаторы, как держать очень горячий путь чтения и как масштабировать хранилище соответствий между короткими и длинными URL.

Этот кейс особенно полезен тем, что на небольшом примере заставляет обсуждать , , кэширование, доступность и цену ошибок в самом востребованном пользовательском сценарии.

Глава 8

Alex Xu: URL Shortener

Детальный разбор в книге System Design Interview

Читать обзор

Зачем нужен сервис сокращения ссылок

Удобство

Короткие ссылки легче запомнить, отправить в соцсетях и использовать в SMS.

Аналитика

Можно отслеживать клики, географию пользователей и источники трафика.

Контроль

Можно отключить ссылку, задать срок действия или защитить её паролем.

Требования

Функциональные

  • FR1
    Создание короткой ссылки из длинного URL
  • FR2
    Редирект по короткой ссылке на оригинальный URL
  • FR3
    Время жизни ссылки (TTL, опционально)
  • FR4
    Пользовательский псевдоним для ссылки (опционально)

Нефункциональные

  • NFR1
    100 млн новых URL в день
  • NFR2
    Соотношение чтения к записи 10:1 → 1 млрд редиректов в день
  • NFR3
    Задержка редиректа < 100 мс
  • NFR4
    Доступность 99.9%

Быстрая оценка масштаба

Нагрузка

  • Запись: 100 млн/день = 1,160 QPS
  • Чтение: 1 млрд/день = 11,600 QPS
  • Пик: ~23,000 QPS (в 2 раза выше среднего)

Хранилище

  • Средний размер URL: 500 байт
  • 100 млн × 500 байт = 50 ГБ/день
  • 5 лет: 50 ГБ × 365 × 5 ≈ 90 ТБ

Длина короткой ссылки

Сколько символов нужно для уникального идентификатора? Используем base62 (a-z, A-Z, 0-9):

ДлинаКомбинацииСсылок за 5 лет
6 символов62⁶ = 56.8BНе хватит
7 символов62⁷ = 3.5T✓ Достаточно
8 символов62⁸ = 218TС запасом

Вывод: 7 символов base62 = 3.5 триллиона комбинаций. При 100 млн URL в день этого хватит примерно на 96 лет.

Стратегии генерации идентификаторов

1
Хэширование и обработка коллизий

Берём MD5/SHA256 от URL, затем первые 7 символов и проверяем, не возникла ли коллизия.

✓ Плюсы:
  • Детерминированно: один и тот же URL даёт один и тот же хэш
  • Нет единой точки отказа
✗ Минусы:
  • Коллизии требуют повторной попытки и обращения к БД
  • Сложнее поддерживать пользовательские псевдонимы

2
Уникальный генератор ID + Base62
Рекомендуется

Получаем уникальный числовой ID и переводим его в base62.

✓ Плюсы:
  • Гарантированно уникальный (без коллизий)
  • Простая логика
  • Легко поддерживать пользовательские псевдонимы
✗ Минусы:
  • Нужен отдельный сервис генерации ID
  • Одинаковые URL могут приводить к разным коротким ссылкам

Варианты генератора идентификаторов

База данных с автоинкрементом

Простое решение с автоинкрементным первичным ключом.

⚠️ Единая точка отказа, плохо масштабируется

Несколько узлов записи

Два сервера: один выдаёт чётные ID, другой — нечётные.

✓ Простое масштабирование, но ограничено числом узлов

UUID

128-битный уникальный идентификатор, который можно генерировать на клиенте.

⚠️ Слишком длинный: 36 символов плохо подходят для короткой ссылки

Snowflake ID
Рекомендуется

64-битный ID: метка времени + датацентр + машина + порядковый номер.

✓ Распределённый, упорядочивается по времени и остаётся компактным

Snowflake

Twitter/X: Snowflake ID

Детальный разбор алгоритма генерации ID

Читать обзор

Верхнеуровневая архитектура

Схема архитектуры

Нажмите на путь, чтобы подсветить его
Клиент

Браузер / приложение

Балансировщик

Пограничная маршрутизация

Сервис ссылок

API без состояния

Путь чтения

Кэш

Redis

База данных

PostgreSQL / Cassandra

Путь записи

Генератор ID

Snowflake

База данных

PostgreSQL / Cassandra

Подсветка пути

Промах кэша показан пунктирной линией к базе данных.

Путь записи
Путь чтения

Путь записи

  1. 1. Клиент отправляет длинный URL.
  2. 2. Генератор ID выдаёт уникальный идентификатор.
  3. 3. Преобразуем ID в base62 и получаем короткую ссылку.
  4. 4. Сохраняем соответствие в БД.
  5. 5. Возвращаем короткую ссылку клиенту.

Путь чтения

  1. 1. Клиент запрашивает короткую ссылку.
  2. 2. Сначала проверяем кэш (Redis).
  3. 3. При промахе кэша идём в БД.
  4. 4. Обновляем кэш.
  5. 5. Возвращаем HTTP 301/302.

301 и 302: что выбрать для редиректа

301 Moved Permanently

Браузер кэширует редирект, поэтому следующие запросы могут идти сразу на целевой URL.

✓ Меньше нагрузки на сервер

✗ Труднее полноценно отслеживать клики на стороне сервиса

302 Found
Рекомендуется

Браузер не кэширует редирект, поэтому каждый клик проходит через сервис.

✓ Полная аналитика кликов

✓ Можно менять целевой URL

Модель данных

Таблица `urls`

ПолеТипОписание
short_urlVARCHAR(7)Первичный ключ, кодируется в base62
original_urlTEXTОригинальный длинный URL
user_idBIGINTСоздатель ссылки (опционально)
created_atTIMESTAMPДата создания
expires_atTIMESTAMPTTL (null = бессрочно)

Глубже

Database Internals

Индексы, B-деревья и оптимизация для систем с преобладанием чтения

Читать обзор

Стратегия кэширования

Соотношение чтения к записи 10:1 делает кэширование критически важным. Redis помогает держать самые востребованные короткие ссылки рядом с приложением.

Стратегия

  • Cache-aside: сначала читаем из кэша, при промахе идём в БД
  • LRU eviction: вытесняем редко используемые ссылки
  • Write-through: при создании сразу записываем данные в кэш

Размер кэша

20% дневных чтений × средний размер URL

= 200M × 500B = 100GB

→ кластер Redis с репликацией

CDN

Content Delivery Network

Геораспределённое кэширование для глобальных систем

Читать обзор

Выбор базы данных

PostgreSQL

  • ✓ ACID гарантии
  • ✓ Простота использования
  • ✓ Подходит для умеренных нагрузок
  • ✗ Сложнее горизонтальное масштабирование

Cassandra / DynamoDB
Для масштаба

  • ✓ Линейное горизонтальное масштабирование
  • ✓ Высокая доступность без единой точки отказа
  • ✓ Оптимизировано под преобладание записи
  • ✗ Согласованность в конечном счёте

Что важно проговорить на интервью

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

Что стоит показать

• Как работает base62 и почему длины в 7 символов достаточно

• Какие компромиссы есть между хэшированием и генератором ID

• Почему 301 и 302 по-разному влияют на аналитику

• Почему в системе с преобладанием чтения главный акцент — кэширование

Частые уточняющие вопросы

• Как обрабатывать одинаковые URL?

• Как поддержать пользовательские псевдонимы?

• Как удалять ссылки с истекшим сроком действия?

• Как защищаться от злоупотреблений?

Связанные главы

  • Принципы проектирования масштабируемых систем - даёт базовые ориентиры по задержке и пропускной способности и помогает оценивать компромиссы в URL Shortener при росте нагрузки.
  • Стратегии кэширования: Cache-Aside, Read-Through, Write-Through, Write-Back - углубляет путь чтения: частоту попаданий в кэш, инвалидацию и выбор подходящего паттерна кэширования для редиректов.
  • Rate Limiter - нужен для защиты API создания коротких ссылок и редиректов от злоупотреблений, ботов и пиковых всплесков трафика.
  • Репликация и шардинг - показывает, как масштабировать хранилище соответствий между короткими и длинными ссылками по мере роста объёма и QPS.
  • API Gateway - дополняет внешний контур сервиса: маршрутизацию, аутентификацию, ограничение нагрузки и пограничные политики для публичного API.
  • CDN - расширяет тему глобальной доставки и периферийного кэширования, чтобы ускорять редиректы в разных регионах.
  • System Design Interview — An Insider's Guide - содержит классический разбор TinyURL для интервью с пошаговой логикой вопросов и решений.

Чтобы отмечать прохождение, включи трекинг в Настройки