Spring Boot Cache:缓存驱逐前自动更新数据库的配置方法咨询
Spring缓存驱逐前自动同步数据库的实现方案
完全可以实现这个需求,核心思路是扩展Spring Cache的缓存实现类,在驱逐缓存对象的逻辑前插入数据库同步操作,以下是具体落地方案:
1. 扩展本地缓存实现(以ConcurrentMapCache为例)
如果使用本地内存缓存,可通过自定义Cache和CacheManager拦截驱逐动作:
自定义带同步逻辑的Cache类
public class SyncOnEvictCache extends ConcurrentMapCache { private final YourEntityRepository entityRepository; public SyncOnEvictCache(String name, ConcurrentMap<Object, Object> store, boolean allowNullValues, YourEntityRepository repository) { super(name, store, allowNullValues); this.entityRepository = repository; } // 处理单个对象驱逐 @Override public void evict(Object key) { Cache.ValueWrapper wrapper = get(key); if (wrapper != null && wrapper.get() instanceof YourEntity entity) { // 同步更新到数据库 entityRepository.save(entity); } // 执行原生驱逐逻辑 super.evict(key); } // 处理批量清空缓存 @Override public void clear() { getNativeCache().values().stream() .filter(obj -> obj instanceof YourEntity) .map(obj -> (YourEntity) obj) .forEach(entityRepository::save); // 执行原生清空逻辑 super.clear(); } }
配置自定义CacheManager
@Configuration public class SyncCacheConfiguration { @Autowired private YourEntityRepository entityRepository; @Bean public CacheManager cacheManager() { return new ConcurrentMapCacheManager() { @Override protected Cache createCache(String cacheName) { return new SyncOnEvictCache(cacheName, new ConcurrentHashMap<>(), true, entityRepository); } }; } }
2. 扩展分布式缓存实现(以RedisCache为例)
如果使用Redis等分布式缓存,需扩展RedisCache和RedisCacheManager,核心逻辑类似,需处理序列化/反序列化:
public class SyncOnEvictRedisCache extends RedisCache { private final YourEntityRepository entityRepository; private final RedisSerializer<Object> valueSerializer; public SyncOnEvictRedisCache(String name, RedisCacheWriter cacheWriter, RedisCacheConfiguration config, YourEntityRepository repository) { super(name, cacheWriter, config); this.entityRepository = repository; this.valueSerializer = config.getValueSerializationPair().getSerializer(); } @Override public void evict(Object key) { // 从Redis获取缓存值并反序列化 byte[] keyBytes = getCacheConfiguration().getKeySerializationPair().getSerializer().serialize(key); byte[] valueBytes = getCacheWriter().get(name, keyBytes); if (valueBytes != null) { YourEntity entity = (YourEntity) valueSerializer.deserialize(valueBytes); entityRepository.save(entity); } // 执行原生驱逐逻辑 super.evict(key); } }
对应的RedisCacheManager需重写createRedisCache方法,返回自定义的SyncOnEvictRedisCache实例。
关键注意事项
- 异常处理:数据库同步需添加异常捕获,避免同步失败导致缓存驱逐中断,可根据业务需求添加重试或日志记录
- 性能考量:批量清空缓存时,大量对象同步可能引发数据库性能问题,可考虑异步批量更新
- 序列化兼容:分布式缓存场景下,确保缓存对象实现
Serializable或配置合适的序列化器,避免反序列化失败 - 注解兼容性:方案完全兼容
@Cacheable、@CachePut、@CacheEvict等标准注解,无需修改原有业务代码
内容的提问来源于stack exchange,提问作者tabool
相关产品推荐
相关产品推荐

