使用ReactiveRedisTemplate能否为缓存键设置默认TTL?
ReactiveRedisTemplate 为不同缓存键预设默认TTL的实现方案
当然可以实现,下面提供几种适配ReactiveRedisTemplate的方案,满足不同缓存键预设不同TTL的需求:
方式一:封装自定义缓存服务层(最直接易维护)
- 先维护一个键与TTL的映射配置,明确每个键的过期时间:
private static final Map<String, Long> KEY_TTL_MAP = Map.of( "key1", 100L, // key1 过期时间100秒 "key2", 200L // key2 过期时间200秒 );
- 基于ReactiveRedisTemplate封装通用存值方法,自动匹配对应TTL:
@Service public class ReactiveCacheService { private final ReactiveRedisTemplate<String, Object> reactiveRedisTemplate; // 构造注入ReactiveRedisTemplate public ReactiveCacheService(ReactiveRedisTemplate<String, Object> reactiveRedisTemplate) { this.reactiveRedisTemplate = reactiveRedisTemplate; } // 自动应用预设TTL的存值方法 public Mono<Boolean> putWithDefaultTtl(String key, Object value) { // 找不到对应键的话用默认TTL,这里设为300秒 Long ttl = KEY_TTL_MAP.getOrDefault(key, 300L); return reactiveRedisTemplate.opsForValue().set(key, value, Duration.ofSeconds(ttl)); } // 可按需扩展其他操作,比如putIfAbsentWithDefaultTtl等 }
- 使用时直接调用该服务的方法,无需每次手动指定TTL,自动遵循预设规则。
方式二:扩展ReactiveRedisTemplate(更灵活的底层封装)
- 自定义带TTL配置的ReactiveRedisTemplate子类,内置键-TTL映射:
public class TtlAwareReactiveRedisTemplate<K, V> extends ReactiveRedisTemplate<K, V> { private final Map<K, Long> keyTtlMap; private final Long defaultTtl; public TtlAwareReactiveRedisTemplate(ReactiveRedisConnectionFactory connectionFactory, RedisSerializer<K> keySerializer, RedisSerializer<V> valueSerializer, Map<K, Long> keyTtlMap, Long defaultTtl) { super(connectionFactory, keySerializer, valueSerializer); this.keyTtlMap = keyTtlMap; this.defaultTtl = defaultTtl; } @Override public ReactiveValueOperations<K, V> opsForValue() { return new TtlAwareReactiveValueOperations<>(super.opsForValue(), keyTtlMap, defaultTtl); } // 自定义ValueOperations实现,重写set方法自动应用TTL private static class TtlAwareReactiveValueOperations<K, V> implements ReactiveValueOperations<K, V> { private final ReactiveValueOperations<K, V> delegate; private final Map<K, Long> keyTtlMap; private final Long defaultTtl; public TtlAwareReactiveValueOperations(ReactiveValueOperations<K, V> delegate, Map<K, Long> keyTtlMap, Long defaultTtl) { this.delegate = delegate; this.keyTtlMap = keyTtlMap; this.defaultTtl = defaultTtl; } // 重写无timeout参数的set方法,自动应用预设TTL @Override public Mono<Boolean> set(K key, V value) { Long ttl = keyTtlMap.getOrDefault(key, defaultTtl); return delegate.set(key, value, Duration.ofSeconds(ttl)); } // 其他方法直接委托给原实现,保留手动指定TTL的能力 @Override public Mono<Boolean> set(K key, V value, Duration timeout) { return delegate.set(key, value, timeout); } // 省略其他接口方法的委托实现(可直接调用delegate对应方法) } }
- 在配置类中注册自定义模板:
@Configuration public class RedisConfig { @Bean public TtlAwareReactiveRedisTemplate<String, Object> ttlAwareReactiveRedisTemplate(ReactiveRedisConnectionFactory connectionFactory) { Map<String, Long> keyTtlMap = Map.of( "key1", 100L, "key2", 200L ); StringRedisSerializer keySerializer = new StringRedisSerializer(); Jackson2JsonRedisSerializer<Object> valueSerializer = new Jackson2JsonRedisSerializer<>(Object.class); // 默认TTL设为300秒 return new TtlAwareReactiveRedisTemplate<>(connectionFactory, keySerializer, valueSerializer, keyTtlMap, 300L); } }
- 使用时注入
TtlAwareReactiveRedisTemplate,调用opsForValue().set(key, value)即可自动应用预设TTL。
补充:结合Spring Cache注解的场景
如果你的项目用Spring Cache注解(如@Cacheable),可以搭配ReactiveRedisCacheManager配置,逻辑和你熟悉的RedisCacheManager一致,只是用响应式版本:
@Bean public ReactiveRedisCacheManager reactiveRedisCacheManager(ReactiveRedisConnectionFactory connectionFactory) { // 默认缓存配置,TTL 300秒 RedisCacheConfiguration defaultConfig = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofSeconds(300)); // 不同缓存名称对应不同TTL Map<String, RedisCacheConfiguration> cacheConfigs = new HashMap<>(); cacheConfigs.put("key1Cache", RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(100))); cacheConfigs.put("key2Cache", RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(200))); return ReactiveRedisCacheManager.builder(connectionFactory) .cacheDefaults(defaultConfig) .withInitialCacheConfigurations(cacheConfigs) .build(); }
使用时通过@Cacheable(cacheNames = "key1Cache")指定缓存名称,就能自动应用对应TTL。
内容的提问来源于stack exchange,提问作者Andre Hrs
相关产品推荐
相关产品推荐

