缓存击穿解决途径——二级缓存+互斥锁 Java实现

1 篇文章 0 订阅

首先是互斥锁。
优点:能够根据请求的key加锁,提高了并发性。
缺点:GC不友好,不是分布式的。

public final class MutexLock {

    private static final ConcurrentHashMap<String,CountDownLatch> locks=new ConcurrentHashMap<>();

    public static boolean tryLock(String key){
        //能过滤掉后持有相同key的线程
        return !locks.containsKey(key);
    }

    public static void lock(String key){
        //多线程持有相同的key并发执行时,可能同时调用 {@code lock(key)},但只有一个线程能成功
        //并发时阻塞的线程只能等着,其他持有相同key的线程可能通过{@code tryLock(key)}判断后去做其他的事情
        //对GC不友好,因为会new很多CountDownLatch,但不会超多最大线程数。
        while(locks.putIfAbsent(key,new CountDownLatch(1))!=null){
            CountDownLatch lock=locks.get(key);
            try {
                lock.await(50, TimeUnit.MILLISECONDS);
            }catch (InterruptedException e){
                //处理异常
            }
        }
    }

    public static void unLock(String key){
       CountDownLatch lock=locks.remove(key);
       lock.countDown();
    }

}

借助互斥锁解决缓存击穿问题:

 public String getVal(String key){
        //一级缓存,取到直接返回
        String val=getValFromRedis(key);
        if(getValFromRedis(key)==null){
            if(MutexLock.tryLock(key)){
                try {
                    MutexLock.lock(key);
                    val=getValFromRedis(key);
                    if (val==null){
                        val=getValFromMysql(key);
                    }
                     //可以打日志看一下更新的值
                     if (val!=null){
                         updateCache(key,val);
                    }
                }finally {
                    MutexLock.unLock(key);
                }
            }else{
                //二级缓存取
                val=getValFromHbase(key);
                //还取不到,重试
                if(val==null){
                    //重试次数可以配在zk里面
                    int i=3;
                    while(i>0){
                        val=getVal(key);
                        if(val!=null){
                            break;
                        }
                        i--;
                    }
                    //取不到,重试还是取不到
                    if(val==null){
                        //发报警邮件,或记录在什么地方
                    }
                }
            }
        }
        return val;
    }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值