Классический системный собес — спроектировать TinyURL/bit.ly. Разбираем стратегии генерации ID, cache-aside паттерн, узкие места при масштабировании. Пилотный кейс нового /cases формата.
Функциональные:
POST /shorten — принять длинный URL, вернуть короткий токен (7 символов Base62)GET /<short> — 301 редирект на длинный URLНефункциональные:
Client → Load Balancer → API Gateway → URL Service. URL Service использует cache-aside паттерн с Redis перед Postgres. Single AZ для v1; multi-AZ репликация — тема раздела «Bottlenecks».
Интерактивная топология (выше README) показывает рантайм-расположение. ADR'ы на нодах URL Service и Postgres объясняют ключевые trade-off'ы.
Создание короткой ссылки. Happy path POST /shorten:
Резолв с промахом кеша. GET /<short> когда кеш не прогрет:
Три рабочих подхода для генерации коротких токенов:
Счётчик (Snowflake-style). Монотонно растущий integer, закодированный в Base62. Плюсы: нет коллизий, предсказуемый размер. Минусы: требует централизованной координации (DB sequence или сервис распределённого счётчика); раскрывает порядок создания.
Хеш (наш выбор). base62(sha256(long_url + salt))[:7]. Плюсы:
stateless, distributed-friendly, детерминирован для одного и того же URL.
Минусы: возможны коллизии (~6.7B пространство при 7 символах) —
обрабатываем on-write проверкой уникальности + retry с новым salt.
UUID v4. 22-символьный Base62 из UUID. Плюсы: уникальность из коробки. Минусы: слишком длинный для UX-обещания «короткой ссылки».
function shortHash(longUrl, salt = '') {
const hash = sha256(longUrl + salt); // 256-bit
return base62(hash).slice(0, 7); // 7 chars ~ 62^7 = 3.5e12
}
urls растёт линейно.
Решение: TTL-колонка + batched delete job + soft-delete для аналитики.