Как настроить TTL для ключей в кэше
Что проверяют
Знаете ли вы, где именно задаётся TTL в том кэше, который используете, и что происходит в момент истечения. Следом обычно спрашивают, как дать разный TTL разным кэшам в Spring и как не положить базу, когда популярный ключ истёк у всех одновременно.
Как отвечать
Разберите по уровням:
- Redis напрямую:
SET key value EX 60атомарно пишет значение с TTL,EXPIRE key 60ставит его существующему ключу,TTL keyпоказывает остаток. ОбычныйSETповерх ключа сбрасывает TTL, сохранить его можно опциейKEEPTTL; - Spring Cache с Redis: у
@Cacheableатрибута TTL нет. Время задаётся вRedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(10)), для отдельного кэша черезwithCacheConfiguration("prices", ...)у билдераRedisCacheManager, а в Spring Boot общим свойствомspring.cache.redis.time-to-live; - Caffeine:
expireAfterWriteсчитает от записи,expireAfterAccessот последнего обращения,refreshAfterWriteотдаёт старое значение и перезагружает его в фоне. TTL для отдельной записи задаётся черезexpireAfter(Expiry); - Ehcache 3: в XML блок
<expiry><ttl unit="seconds">60</ttl></expiry>, в кодеExpiryPolicyBuilder.timeToLiveExpiration(...).
Значение выбирают по тому, насколько устаревшие данные терпит бизнес: справочник живёт часами, цена минутами. Если нужна точность, TTL служит страховкой, а основная инвалидация идёт по событию через @CacheEvict.
Против одновременного истечения помогают случайный разброс TTL (jitter) и загрузка одним потоком: @Cacheable(sync = true) или LoadingCache в Caffeine, где параллельные запросы за одним ключом ждут одну загрузку.
Где спотыкаются
Ищут параметр TTL в @Cacheable и не знают, что он настраивается в менеджере кэша.
Думают, что Redis удаляет ключ ровно в секунду истечения. Удаление ленивое плюс фоновая выборка: прочитать истёкший ключ нельзя, но память освобождается с задержкой.
Не учитывают сброс TTL при перезаписи. После обычного SET ключ становится вечным, и кэш растёт без ограничений.