У сокращателя ссылок простой внешний интерфейс, но внутри это кейс про очень горячий путь чтения, генерацию коротких идентификаторов и масштабирование хранилища соответствий.
Глава полезна тем, что заставляет отдельно продумать путь записи и путь чтения: что кэшировать, где могут появиться горячие ключи и как не превратить генератор 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Пользовательский псевдоним для ссылки (опционально)
Нефункциональные
- NFR1100 млн новых 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
Путь записи
Snowflake
PostgreSQL / Cassandra
Подсветка пути
Промах кэша показан пунктирной линией к базе данных.
Путь записи
- 1. Клиент отправляет длинный URL.
- 2. Генератор ID выдаёт уникальный идентификатор.
- 3. Преобразуем ID в base62 и получаем короткую ссылку.
- 4. Сохраняем соответствие в БД.
- 5. Возвращаем короткую ссылку клиенту.
Путь чтения
- 1. Клиент запрашивает короткую ссылку.
- 2. Сначала проверяем кэш (Redis).
- 3. При промахе кэша идём в БД.
- 4. Обновляем кэш.
- 5. Возвращаем HTTP 301/302.
301 и 302: что выбрать для редиректа
301 Moved Permanently
Браузер кэширует редирект, поэтому следующие запросы могут идти сразу на целевой URL.
✓ Меньше нагрузки на сервер
✗ Труднее полноценно отслеживать клики на стороне сервиса
302 FoundРекомендуется
Браузер не кэширует редирект, поэтому каждый клик проходит через сервис.
✓ Полная аналитика кликов
✓ Можно менять целевой URL
Модель данных
Таблица `urls`
| Поле | Тип | Описание |
|---|---|---|
| short_url | VARCHAR(7) | Первичный ключ, кодируется в base62 |
| original_url | TEXT | Оригинальный длинный URL |
| user_id | BIGINT | Создатель ссылки (опционально) |
| created_at | TIMESTAMP | Дата создания |
| expires_at | TIMESTAMP | TTL (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 для интервью с пошаговой логикой вопросов и решений.
