Redis缓存能否定义相对TTL?Spring Boot(Java/Kotlin)实现问询
基于最后一次访问的缓存过期(相对TTL)实现方案
当然可以实现这种基于访问的过期策略(也叫Idle TTL),即缓存条目会在最后一次被读取/使用后的指定时间过期,而非创建后的固定时间。下面针对Spring Boot项目(支持Java/Kotlin),分两种常用缓存场景给出实现方案:
一、本地缓存:使用Caffeine
Caffeine是Spring Boot默认推荐的本地缓存实现,原生支持expireAfterAccess策略。
1. 引入依赖
如果是Maven项目,在pom.xml中添加:
<dependency> <groupId>com.github.benmanes.caffeine</groupId> <artifactId>caffeine</artifactId> </dependency>
如果是Gradle Kotlin DSL项目,在build.gradle.kts中添加:
implementation("com.github.benmanes.caffeine:caffeine")
2. 配置缓存管理器
Java配置类
import com.github.benmanes.caffeine.cache.Caffeine; import org.springframework.cache.CacheManager; import org.springframework.cache.caffeine.CaffeineCacheManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.concurrent.TimeUnit; @Configuration public class CaffeineCacheConfig { @Bean public CacheManager cacheManager() { CaffeineCacheManager cacheManager = new CaffeineCacheManager("userDataCache"); cacheManager.setCaffeine(Caffeine.newBuilder() // 设置最后一次访问后10分钟过期 .expireAfterAccess(10, TimeUnit.MINUTES) .maximumSize(2000)); // 可选:限制缓存最大容量,防止内存溢出 return cacheManager; } }
Kotlin配置类
import com.github.benmanes.caffeine.cache.Caffeine import org.springframework.cache.CacheManager import org.springframework.cache.caffeine.CaffeineCacheManager import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import java.util.concurrent.TimeUnit @Configuration class CaffeineCacheConfig { @Bean fun cacheManager(): CacheManager { val cacheManager = CaffeineCacheManager("userDataCache") cacheManager.setCaffeine(Caffeine.newBuilder() .expireAfterAccess(10, TimeUnit.MINUTES) .maximumSize(2000)) return cacheManager } }
3. 业务代码中使用缓存
Java示例
import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; @Service public class UserService { @Cacheable(value = "userDataCache", key = "#userId") public String getUserInfo(String userId) { // 模拟从数据库/远程服务获取数据 return "User info for ID: " + userId; } }
Kotlin示例
import org.springframework.cache.annotation.Cacheable import org.springframework.stereotype.Service @Service class UserService { @Cacheable(value = ["userDataCache"], key = "#userId") fun getUserInfo(userId: String): String { return "User info for ID: $userId" } }
二、分布式缓存:使用Redis
Redis作为分布式缓存,通过Spring Data Redis可以配置基于访问的过期策略,核心是启用timeToIdle属性。
1. 引入依赖
Maven项目pom.xml:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
Gradle Kotlin DSL项目build.gradle.kts:
implementation("org.springframework.boot:spring-boot-starter-data-redis")
2. 配置Redis连接
在application.yml中配置Redis基础信息:
spring: redis: host: localhost port: 6379 # password: your_redis_password # 如有密码则添加
3. 配置Redis缓存管理器
Java配置类
import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.cache.RedisCacheConfiguration; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.connection.RedisConnectionFactory; import java.time.Duration; @Configuration @EnableCaching public class RedisCacheConfig { @Bean public CacheManager cacheManager(RedisConnectionFactory connectionFactory) { RedisCacheConfiguration cacheConfig = RedisCacheConfiguration.defaultCacheConfig() // 设置基础过期时间(配合timeToIdle生效) .entryTtl(Duration.ofMinutes(10)) .computePrefixWith(cacheName -> "cache:" + cacheName + ":") // 启用基于空闲(最后一次访问)的过期重置 .enableTimeToIdle(); return RedisCacheManager.builder(connectionFactory) .cacheDefaults(cacheConfig) .build(); } }
Kotlin配置类
import org.springframework.cache.CacheManager import org.springframework.cache.annotation.EnableCaching import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.data.redis.cache.RedisCacheConfiguration import org.springframework.data.redis.cache.RedisCacheManager import org.springframework.data.redis.connection.RedisConnectionFactory import java.time.Duration @Configuration @EnableCaching class RedisCacheConfig { @Bean fun cacheManager(connectionFactory: RedisConnectionFactory): CacheManager { val cacheConfig = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofMinutes(10)) .computePrefixWith { cacheName -> "cache:$cacheName:" } .enableTimeToIdle() return RedisCacheManager.builder(connectionFactory) .cacheDefaults(cacheConfig) .build() } }
4. 业务代码中使用缓存
和Caffeine的使用方式完全一致,用@Cacheable等注解即可:
Kotlin示例
import org.springframework.cache.annotation.Cacheable import org.springframework.stereotype.Service @Service class OrderService { @Cacheable(value = ["orderDataCache"], key = "#orderId") fun getOrderDetail(orderId: String): String { return "Order detail for ID: $orderId" } }
效果验证
以你的示例场景为例:
- 10:00首次调用方法,缓存条目创建,初始过期时间为10:10
- 10:08再次调用方法命中缓存,该条目的过期时间自动重置为10:18
- 如果10:18前没有再次访问,缓存条目会自动过期
内容的提问来源于stack exchange,提问作者SR3599
相关产品推荐
相关产品推荐

