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

一、缓存穿透

什么是穿透?

前提:模拟一个不存在的订单号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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值