@Cacheable踩坑,服务停住,~lock

1、问题
方法使用@Cacheable注解,服务每次重启后,调到这个方法都服务停住了,日志也不打了。

2、原因
服务停止住了,发现redis会生成key~lock的锁,永不过期,也没有删除。

例如以下,在我们的key 后面加了~lock
在这里插入图片描述
3、解释:

在 Spring Framework 中,@Cacheable 注解用于缓存方法的返回结果。在使用 Redis 作为缓存存储时,你可能会看到以 key~lock 形式存在的键。这通常是为了实现缓存的并发控制和一致性而使用的。

具体来说,key~lock 是为了防止缓存击穿(cache breakdown)或缓存并发写入问题。以下是一些关键点:

  1. 缓存击穿和并发控制

    • 缓存击穿 指的是缓存中存储的数据过期了,导致多个线程同时去访问数据库,造成数据库压力过大。为避免这个问题,系统使用锁来确保只有一个线程能够去从数据源加载数据,而其他线程则等待数据加载完成。
    • 并发控制 确保同一时间只有一个线程可以更新缓存数据。为了防止多个线程同时尝试加载数据到缓存中,系统会使用一个锁来确保数据的正确性和一致性。
  2. key~lock 的作用

    • 当一个线程第一次尝试从缓存中获取数据时,系统会在 Redis 中创建一个类似 key~lock 的临时锁键。
    • 如果其他线程尝试获取相同的缓存数据,它们会看到这个锁,并且会等待锁释放,以避免同时触发多个数据加载操作。
    • 一旦数据加载完成,锁会被删除,从而允许其他线程获取到缓存的数据。

要查看 key~lock 的具体实现,你可以查看 Spring Cache 和 Redis 的相关源码:

  1. Spring Framework 源码
    • @Cacheable 注解及其处理逻辑主要在 org.springframework.cache.annotation 包下。
    • 缓存操作的实现可能涉及到 CacheInterceptor 类,该类负责拦截缓存操作。

该部分源码我没有找到,这段是GPT说明的,如果有同仁找到,麻烦评论告知下

5、说明:

我出现这个原因是我kill -9 服务的端口,服务直接停止,可能导致了这个key~lock还没删除掉,下次要进来读的时候,发现这个锁还在,就在等待。

  1. 锁未释放:如果 Redis 锁没有被正确释放,下次启动时,服务可能会发现锁依然存在,从而无法进行缓存操作或者数据加载。

  2. 恢复机制:为了避免这种情况,通常会在实现中设置锁的超时时间。这样即使服务崩溃,锁也会在超时后自动释放,允许其他服务继续获取缓存数据。

  3. 异常处理:建议在服务中实现适当的异常处理和恢复机制,确保锁不会长时间存在,并尽可能恢复服务的正常运行。

6、建议:

1、服务不要直接kill 掉,可能会出现数据库或者redis事务还没处理完,导致出现一些事故
2、需要经常操作和获取redis缓存的,直接使用redisUtil.get(),直接获取就好,不要使用@Cacheable

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值