Как применяются системы кэширования, например Caffeine или Redis
Что проверяют
Понимаете ли вы разницу между локальным кешем внутри JVM и распределённым, и умеете ли выбрать по задаче. Следом почти всегда спрашивают про инвалидацию: как вы узнаете, что данные в кеше устарели, если у сервиса пять экземпляров.
Как отвечать
Разведите два класса решений:
- Caffeine: кеш в памяти процесса. Доступ без сети и сериализации, вытеснение по алгоритму W-TinyLFU, ограничения
maximumSizeилиmaximumWeight, время жизниexpireAfterWriteиexpireAfterAccess, фоновое обновлениеrefreshAfterWrite, статистика черезrecordStats(). Минус: у каждого экземпляра приложения свой кеш, и после рестарта он пустой; - Redis: отдельный сервер, общий для всех экземпляров. Переживает рестарт приложения, умеет TTL (
SET key value EX 600), структуры данных, атомарные счётчики и pub/sub. Цена: сетевой запрос, сериализация и ещё один компонент, который может упасть.
В Spring оба подключаются через одну абстракцию: @EnableCaching, @Cacheable, @CachePut, @CacheEvict, а под ней CaffeineCacheManager или RedisCacheManager. Клиент Redis по умолчанию в Spring Data Redis это Lettuce.
Когда что брать: справочники, конфигурация и данные, где пара минут устаревания допустима, живут в Caffeine. Сессии, лимиты запросов и данные, которые должны быть одинаковы на всех узлах, живут в Redis. Под большой нагрузкой делают два уровня: Caffeine перед Redis, а об изменениях оповещают через pub/sub, чтобы узлы сбросили локальную копию.
Упомяните защиту от одновременной загрузки одного ключа: cache.get(key, loader) в Caffeine вычисляет значение один раз, остальные потоки ждут результат, а не идут в базу толпой.
Где спотыкаются
Вызывают метод с @Cacheable из того же класса. Вызов идёт мимо прокси, и кеш молча не работает.
Создают Caffeine без maximumSize. Такой кеш ничем не ограничен и растёт до OutOfMemoryError.
Не знают политики вытеснения Redis. По умолчанию maxmemory-policy равна noeviction: когда заданный maxmemory исчерпан, Redis отвечает ошибкой на запись, а не выбрасывает старые ключи. Для кеша обычно ставят allkeys-lru или allkeys-lfu.