Что такое Redis и его особенности
Что проверяют
Понимаете ли вы, где Redis уместен и где он теряет данные, а не только слово «кэш». Для Go-разработчика следом идёт практика: какой клиент, как устроен пул, как обработать отсутствие ключа и как не устроить лавину запросов в базу при истечении TTL.
Как отвечать
Redis это хранилище «ключ-значение» в памяти со структурами данных. Команды исполняются в одном потоке, поэтому каждая атомарна сама по себе; с версии 6 сетевой ввод-вывод можно раздать на I/O-потоки, но исполнение остаётся однопоточным.
Что стоит назвать:
- структуры: строки, хэши, списки, множества, sorted sets (рейтинги, окна для rate limiter), streams с группами потребителей, HyperLogLog, bitmap, geo;
- TTL и вытеснение:
EXPIREна ключ иmaxmemory-policy. По умолчанию стоитnoeviction, и при заполнении памяти запись падает с ошибкой; для кэша ставятallkeys-lruилиallkeys-lfu; - персистентность: RDB-снапшоты и AOF, при
appendfsync everysecтеряется до секунды записей; - масштабирование: асинхронная репликация с Sentinel или Cluster на 16384 слота. Ключи многоключевой команды держат в одном слоте через hash tag
{user:42}; - лицензия: в 2024 году Redis ушёл с BSD, появился форк Valkey, который многие облака дают вместо него.
В Go стандарт это github.com/redis/go-redis/v9. Каждая команда принимает context.Context, отсутствие ключа приходит ошибкой redis.Nil, пул по умолчанию 10 соединений на каждый GOMAXPROCS. Пачки команд шлют через Pipelined, атомарные связки через TxPipelined или Lua-скрипт.
Где спотыкаются
Не отличают redis.Nil от настоящей ошибки и на промахе кэша отдают 500. Проверять нужно через errors.Is(err, redis.Nil).
Зовут KEYS * в проде. Команда перебирает все ключи и блокирует единственный поток исполнения, вместо неё есть SCAN.
Забывают про одновременное истечение популярного ключа: сотни горутин идут в базу за одним значением. Спасают singleflight из golang.org/x/sync и случайный разброс TTL.