如何为RedisCacheManager设置特定时间(如午夜)过期缓存?
如何让RedisCacheManager的缓存在特定时间(如午夜)过期?
刚上手RedisCacheManager,已经搞定了一天有效期的缓存,现在想改成特定时间(比如午夜)过期?这需求太常见了,我给你分享几个靠谱的实现方式:
方法一:动态计算到目标时间的间隔(单个Key生效)
这是最直接的思路,不用改动太多现有代码。核心就是不使用固定的过期时长,而是计算当前时间到你目标过期时间(比如次日午夜)的毫秒差,把这个差值作为缓存的过期时间。
举个Spring项目里的Java代码示例:
// 计算当前时间到次日午夜的毫秒数 LocalDateTime now = LocalDateTime.now(); // 构造次日0点0分0秒的时间 LocalDateTime midnight = now.plusDays(1) .withHour(0) .withMinute(0) .withSecond(0) .withNano(0); // 计算时间差 long expireMillis = Duration.between(now, midnight).toMillis(); // 存入缓存时使用这个动态计算的过期时间 redisCacheManager.getCache("myCache").put("targetKey", "cacheValue", expireMillis);
注意:每次存入缓存时都要重新计算这个间隔,因为不同时间存入的Key,到午夜的剩余时间是不一样的。
方法二:自定义CacheManager全局配置(批量生效)
如果想让某一类甚至所有缓存都默认在午夜过期,可以自定义RedisCacheConfiguration,动态生成过期时间。
不过要注意:直接在Bean初始化时计算一次过期时间是不行的(因为CacheManager是单例,只会用启动时的计算值),所以要确保每次创建缓存时都能动态获取最新的过期间隔。
示例代码如下:
@Bean public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) { RedisCacheWriter cacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory); // 基础缓存配置(序列化、默认规则等) RedisCacheConfiguration baseConfig = RedisCacheConfiguration.defaultCacheConfig() .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())); return RedisCacheManager.builder(cacheWriter) // 全局默认配置(如果需要所有缓存都用午夜过期,就把这里的entryTtl改成动态计算的) .cacheDefaults(baseConfig.entryTtl(Duration.ofMillis(calculateMidnightExpireMillis()))) // 也可以给特定缓存单独配置 .withCacheConfiguration("userCache", baseConfig.entryTtl(Duration.ofMillis(calculateMidnightExpireMillis()))) .build(); } // 封装计算过期时间的工具方法 private long calculateMidnightExpireMillis() { LocalDateTime now = LocalDateTime.now(); LocalDateTime midnight = now.plusDays(1).truncatedTo(ChronoUnit.DAYS); return Duration.between(now, midnight).toMillis(); }
小提示:如果你的项目里有多个缓存需要不同的过期规则,用withCacheConfiguration逐个配置就好,灵活性很高。
方法三:定时任务主动清理缓存(简单粗暴)
如果你的业务场景不需要精确到每个Key的过期时间,只要每天午夜清空指定缓存就行,那用定时任务是最简单的方案。
比如用Spring的@Scheduled注解实现:
// 每天0点0分0秒执行 @Scheduled(cron = "0 0 0 * * ?") public void clearCacheAtMidnight() { // 清空指定缓存 redisCacheManager.getCache("myCache").clear(); // 如果要清空所有缓存,可以遍历cacheManager.getCacheNames()逐个清理 }
注意:这种方式会直接清空整个缓存,不管里面的Key是什么时候存入的,适合那些每天必须刷新的缓存场景(比如每日统计数据)。
内容的提问来源于stack exchange,提问作者PmanAce
相关产品推荐
相关产品推荐

