Redis 缓存穿透和缓存雪崩解决方案

导读:本篇文章讲解 Redis 缓存穿透和缓存雪崩解决方案,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

一、缓存穿透

什么是穿透?

前提:模拟一个不存在的订单号xxx

1、Resi 中无此值

2、MySQL 中也我也此值,但是一直被查询

缓存层和持久层都不会命中,在日常工作中出于容错的考虑,如果从持久层查不到数据则不写入缓存层,缓存穿透将导致不存在的数据每次请求都要到持久层去查询,失去了缓存保护后端持久的意义。

解决方案:

1. 缓存空对象

缓存空对象:是指在持久层没有命中的情况下,对key进行set (key,null)

缓存空对象会有两个问题:

第一,value为null 不代表不占用内存空间,空值做了缓存,意味着缓存层中存了更多的键,需要更多的内存空间,比较有效的方法是针对这类数据设置一个较短的过期时间,让其自动剔除。

第二,缓存层和存储层的数据会有一段时间窗口的不一致,可能会对业务有一定影响。例如过期时间设置为5分钟,如果此时存储层添加了这个数据,那此段时间就会出现缓存层和存储层数据的不一致,此时可以利用消息系统或者其他方式清除掉缓存层中的空对象

2. 布隆过滤器拦截

对订单表所有数据查询出来放到布隆过滤器,经过布隆过滤器处理的数据很小(只存 0 或 1)

每次查订单表前,先到过滤器里查询当前订单号状态是0还是1, 0的话代表数据库没有数据,直接拒绝查询

缓存雪崩

什么是雪崩?

由于缓存层承载着大量请求,有效地保护了存储层,但是如果缓存层由于某些原因不可用(宕机)或者大量缓存由于超时时间相同在同一时间段失效(大批 key 失效/热点数据失效),大量请求直接到达存储层,存储层压力过大导致系统雪崩。

解决方案如下:

1、设置热点数据永远不过期。

2、加互斥锁,互斥锁参考代码如下

public static String getDate(String key) throws InterruptedExeception {
    //从缓存中读取数据
    String result = getDateFromRedis(key);
    //缓存中不存在数据
    if (null == result) {
        //去获得锁,获取成功,去数据库获取数据
        if (reenLock.tryLock()) {
            //从数据库中获取数据
            result = getDateFromMysql(key);
            //更新缓存数据
            if (null != result) {
                setDataToCache(key, result);
            }
            //释放锁
            reenLock.unlock();
        }
        //获取锁失败
        else {
            //暂停100ms再重新去获取数据
            Thread.sleep(100);
            retsult = getData(key);
        }
    }
    return result;
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/68386.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!