Как спроектировать сервис сокращения ссылок и что нужно учесть
Что проверяют
Понимаете ли вы, где в этой системе настоящая нагрузка и как её держит сервис на Go: редирект, кеш, генерация уникального кода без коллизий при нескольких инстансах. Уточняют обычно про генерацию ID и про подсчёт кликов, который не замедляет редирект.
Как отвечать
Проговорите требования и цифры: чтений примерно в 100 раз больше, чем записей, семь символов Base62 дают около 3,5 трлн кодов. Затем каркас:
- генерация ID: монотонный счётчик в Base62. Чтобы инстансы не ходили в базу за каждым номером, каждый берёт диапазон, например по 10 000, и раздаёт его из памяти через
atomic.Int64. Альтернатива: ID в духе Snowflake из времени, номера узла и счётчика. Случайный код требует уникального ограничения в базе; - хранение: PostgreSQL с первичным ключом по коду или хранилище ключ-значение вроде Cassandra и ScyllaDB, если нужна запись в нескольких дата-центрах. Схема простая, поэтому выбор решает эксплуатация, а не модель данных;
- редирект:
http.Redirect(w, r, target, http.StatusFound). 302 оставляет клики видимыми для сервера, 301 кешируется браузером; - кеш: локальный LRU в процессе плюс Redis. Против лавины одинаковых промахов
singleflightизgolang.org/x/syncсклеивает параллельные запросы к одному коду в один поход в базу; - аналитика: событие клика кладётся в буферизированный канал, фоновые горутины пачками пишут в Kafka или ClickHouse. При переполнении канала событие лучше потерять, чем задержать редирект;
- эксплуатация:
contextс таймаутами на каждый поход в базу и кеш, пулpgxpool, graceful shutdown черезServer.Shutdown, rate limit на создание черезgolang.org/x/time/rate.
Где спотыкаются
Генерируют случайный код и проверяют его отдельным SELECT перед INSERT. Между проверкой и вставкой успевает пройти второй запрос, гонку закрывает только уникальный индекс.
Пишут счётчик кликов синхронным UPDATE на каждый редирект. Популярная ссылка превращается в горячую строку с очередью блокировок.
Запускают горутину на каждое событие без ограничений. Под пиком это тысячи горутин и соединений к базе, надёжнее фиксированный пул воркеров.