Какие плюсы и минусы использования Redis и куки для хранения данных
Что проверяют
Умеете ли вы решить, где держать состояние пользователя в Go-сервисе, запущенном в нескольких репликах за балансировщиком. Правильная рамка: Redis это состояние на сервере, кука это состояние у клиента, и часто они работают вместе. Следом спросят, как сделать выход со всех устройств.
Как отвечать
Опишите две схемы и их цену.
Идентификатор сессии в куке, данные в Redis:
- плюсы: реплики остаются без состояния, любая из них достаёт сессию по ключу через
go-redis(rdb.Get(ctx, "sess:"+id)). Сессию можно удалить или продлить мгновенно, TTL ставится при записи. Заодно Redis закрывает rate limiting и распределённые блокировки; - минусы: сетевой запрос на каждый входящий HTTP-запрос, поэтому нужен пул соединений и таймаут через
context. Отказ Redis означает отказ авторизации, если не продумана деградация. Память ограничена, поведение при заполнении задаётmaxmemory-policy.
Всё состояние в куке:
- плюсы: никаких внешних зависимостей, запрос обслуживается без похода в сеть;
- минусы: около 4 КБ на куку, и куки едут в каждом запросе к домену, включая статику. Подделку исключают подписью HMAC или шифрованием, например через
gorilla/securecookie. Отозвать такую куку до истечения срока нельзя без списка отзыва, а он опять живёт на сервере.
В Go куку ставят через http.SetCookie(w, &http.Cookie{...}) с полями HttpOnly: true, Secure: true, SameSite: http.SameSiteLaxMode, MaxAge и Path. Ключ подписи берут из окружения, а не из кода.
Где спотыкаются
Забывают context с таймаутом при обращении к Redis. Когда Redis тормозит, горутины копятся на ожидании, и сервис падает вслед за ним.
Хранят в куке JSON без подписи и доверяют ему на сервере. Кука это пользовательский ввод, как и тело запроса.
Генерируют идентификатор сессии через math/rand или счётчик. Нужен crypto/rand и не меньше 128 бит случайности, иначе сессию можно подобрать.