You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 08:14:57