@Cacheable 对数据库变更的响应机制
在Redis缓存应用,我们会出现当数据库中的数据发送变化,这会导致数据库与Redis之间数据不一致,那如何处理类似的这种问题?
@Cacheable 不会自动监听数据库变化,它是一个被动的缓存机制,只在方法被调用时检查缓存是否存在。当数据库有新增或修改记录时,你需要主动管理缓存更新
@Cacheable 检查的是缓存中是否存在与当前方法调用匹配的键值对,而不是简单地检查缓存是否存在。具体来说:
-
检查缓存键(Key)是否存在
每次调用被@Cacheable注解的方法时,Spring 会根据以下两个要素生成一个唯一的缓存键:value/cacheNames:缓存名称(如"users")key:键表达式(如#id,SpEL 表达式生成的键值)
如果该键在缓存中存在,则直接返回对应的值,不执行方法体;如果不存在,才会执行方法体,并将结果存入缓存。
-
与“缓存存在”的区别
“缓存存在”指的是 Redis 中是否有对应的数据库或存储空间,而@Cacheable检查的是缓存中是否存在特定键值对。例如:
被动触发机制@Cacheable 不会主动轮询或监听数据库变化,只有通过方法调用才会触发缓存检查。这意味着:
- 如果数据库数据变化但未调用相关方法,缓存不会更新。
- 即使数据库变化后调用了其他方法(如新增数据的方法),只要不触发带有
@Cacheable的方法,缓存依然不会更新。

如何保持缓存与数据一致
1.手动清除缓存(推荐)
在修改数据的方法上添加 @CacheEvict,强制清除旧缓存:
@CacheEvict(value = "users", key = "#id")
public void updateUser(Long id, User user) {
userRepository.save(user);
}
在方法没有参数的情况下,如果要清除固定键 userList::cacheRedis 的缓存,可以通过以下方式实现:
直接在 @CacheEvict 注解中 显式指定固定键值,配合 value 指定缓存名称:
@CacheEvict(value = "userList", key = "'cacheRedis'")
public void updateUser() {
// 数据库更新操作
// userRepository.save(...);
}
2.设置缓存过期时间(TTL)
通过 Redis 配置,让缓存自动过期并重新加载:
@Configuration
@EnableCaching
public class RedisConfig {
@Bean
public RedisCacheManagerBuilderCustomizer ttlCustomizer() {
return builder -> builder
.withCacheConfiguration("users",
RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(30)) // 30分钟过期
);
}
}

浙公网安备 33010602011771号