双重判定锁来解决缓存击穿问题

缓存击穿场景

缓存击穿是指:当热点数据过期或者不存在时,此时正好有大量请求访问热点数据,这些请求就会直接访问数据库,造成数据库的压力骤增,严重时造成宕机。

解决缓存击穿有几种方案:

  1. 缓存预热
    对热点数据进行预加载,当活动开始时,提前将热点数据从数据库加载到缓存中,可以避免海量请求第一次访问热点数据时需要从数据库读取的流程。
  2. 热点数据永不过期
    对于已知的热点数据,设置过期时间为-1,这样就不会有缓存击穿的情况出现了。
  3. 分布式锁
    使用分布式锁,使得只有一个请求可以访问数据库,避免大量请求并发访问数据库。
    但是这种方法存在一定弊端:
    获取分布式锁的请求,都会执行查询数据库并且更新缓存,理论上只有第一次加载数据库请求的记录是有效的。所以这里采用双重判定锁的形势来解决。

    即在获取到分布式锁后,再次进行判断缓存是否存在,如果存在则直接返回。如果不存在,才执行访问数据库并更新缓存的操作

缓存击穿使用 lock 或者 tryLock 同样有所讲究,需要视场景而定:

lock:

获取锁,成功就执行操作,失败就阻塞等待。

trylock:

获取锁,成功返回true,失败则直接返回false,不用阻塞等待。

Lock源码

csharp 复制代码
public interface Lock {
    /**
     * Acquires the lock.
     */
    void lock();
 
    /**
     * Acquires the lock unless the current thread is
     * {@linkplain Thread#interrupt interrupted}.
     */
    void lockInterruptibly() throws InterruptedException;
 
    /**
     * Acquires the lock if it is free within the given waiting time and the
     * current thread has not been {@linkplain Thread#interrupt interrupted}.
     */
    boolean tryLock();
 
    /**
     * Acquires the lock if it is free within the given waiting time and the
     * current thread has not been {@linkplain Thread#interrupt interrupted}.
     */
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
 
    /**
     * Releases the lock.
     */
    void unlock();
 
    /**
     * Returns a new {@link Condition} instance that is bound to this
     * {@code Lock} instance.
     */
    Condition newCondition();
}

发生极端情况时,lock和trylock如何选择?

如果希望确保线程能够按照特定的顺序访问共享资源,并且不介意可能的等待时间,那么lock方法是一个不错的选择,但是,如果希望避免线程长时间等待,并且能够处理未能立即获得锁的情况,那么tryLock方法可能更适合。

那么trylcok具体对应于什么样的场景呢?

如果是双十一抢优惠券或者真的是海量访问,在用户占便宜的情况下,推荐使用trylock,因为用户会因为失败而自己刷新页面,海量访问也推荐使用trylock,因为如果使用lock对于用户的体验非常不好。

相关推荐
程序猿乐锅11 小时前
【黑马点评 | 第八篇】Redisson分布式锁
java·数据库·spring boot·redis·分布式·spring·缓存
阿狗童鞋12 小时前
Redis实战指南
数据库·redis·缓存
程序猿乐锅18 小时前
一文讲透缓存穿透、击穿和雪崩
java·redis·spring·缓存·mybatis
wjjzhbb18 小时前
Jenkins到ArgoCD——GitOps持续交付实践
运维·缓存·jenkins·argocd
程序猿乐锅18 小时前
【黑马点评 | 第七篇】Redis 分布式锁的两种实现
java·数据库·redis·分布式·spring·缓存
旋生万物1 天前
Redis 缓存雪崩?不是 TTL 一样,是过期相位同步塌陷(附打散脚本)
redis·缓存·aigc·螺旋生成论·螺旋相位
全栈弄潮儿²⁰²⁴7 天前
AI Agent 开发实战(30):限流、缓存与成本控制
人工智能·gpt·缓存·agent·限流·agi·成本控制
Together_CZ8 天前
DeepSeek-V4.1-Flash:Pushing the Limits of KV Cache Compression——推动 KV 缓存压缩的极限
缓存·llm·compression·kv cache·deepseek·v4.1-flash·推动 kv 缓存压缩的极限
Pioneer000018 天前
我用 Redis + 网关做多模型 API 路由:缓存命中率 95%+ 的工程实践
人工智能·redis·后端·缓存·性能优化·架构
hweiyu009 天前
Redis命令:MSETNX
redis·缓存