缓存-key不存在

476 阅读4分钟

背景

什么缓存击穿啊,穿透啊,雪崩啊,不管叫什么名字,本质上,基本上所有的缓存问题,都是由于key不存在导致的。

比如,
1.key存在,但是过期,导致某一时刻key不存在。
2.key本来就不存在。

只要key不存在,不管是什么原因导致key不存在,所有的流量都会到达数据库。数据库就会死翘翘。

分类

key过期,导致key某一时刻不存在
1.单个key过期
2.多个key同时过期

key本来就不存在
1.单个key不存在
2.多个key不存在

单个key过期

过期会导致什么问题呢?

流量高峰。即高并发。高并发导致的问题就是,数据库受不了。

本来缓存,就是为了解决数据库受不了的问题的,现在key过期了,导致流量全部跑到数据库,数据库扛不住。


解决方案

如何解决?就是读不走数据库,走缓存。现在缓存过期了,必须要走缓存,怎么办?核心还是不让流量到数据库。

这个不让,不是说一个都不让,而是同一时刻,只能有一个流量请求数据库。其他流量,都不能请求数据库。

这个是核心思路。


代码

public String get(key) {
    String value = redis.get(key);
    if (value == null) { //代表缓存值过期
        //设置3min的超时,防止del操作失败的时候,下次缓存过期一直不能load db
        if (redis.setnx(key_mutex, 1, 3 * 60) == 1) {  //代表设置成功
            value = db.get(key);
            redis.set(key, value, expire_secs);
            redis.del(key_mutex);
            return value;
        } else {  //这个时候代表同时候的其他线程已经load db并回设到缓存了,这时候重试获取缓存值即可
            sleep(50);
            get(key);  //重试
        }
    } else { //数据存在,直接返回
        return value;      
    }
}

说明
基于redis分布式锁,确保同一时刻,只有一个流量请求数据库。

多个key同时过期

什么情况下会导致多个key同时过期?

1.设置的时候,多个key的过期时间一样
2.缓存服务器重启,比如memcache


怎么解决?

让不同的key,过期时间不一样。比如,过期时间后面再加一个时间的随机数。


概念

这里要解决的问题,其实就是缓存雪崩的问题。

单个key本来就不存在

什么情况会导致key本来就不存在?

很有可能是被别人攻击。


解决方法?

核心思路,还要一样,就是不让流量到数据库。怎么办?还是缓存。就是key不存在,也要缓存。说白了,就是查询key的时候,value为null,这个时候1.读数据库2.写到缓存。

其实,这里的步骤,和过期的解决方法,是一模一样的。所以,解决方法和实现代码是一样的。

唯一的区别,就是过期的情况,是你的系统,本来就是需要缓存这个key的。但是现在这里的情况,是本来你的系统是不需要缓存这个key的,但是为了避免击垮数据库,才去缓存这个key的。本质的区别,就在这里。


概念

这里要讨论的问题,其实就是缓存击穿的概念。

多个key本来就不存在

背景

黑客攻击的时候,不可能只使用一个不存在的key。要攻击,也是不断的变换着使用不同的不存在的key去攻击。


解决方法

布隆管理器。主要解决海量数据集合里,校验某个数据是否在集合里。本质是基于bit的思想。

大致思路是
1.海量数据集合,保存了所有本来应该存在的key
2.每次请求的时候,校验key是否在集合里,在,就读缓存;不在,就直接返回,即不让请求访问数据库。

总结

所有的解决方案,基本的核心思路就是,不让访问数据库。即要么访问缓存,要么直接返回。

如果同一时刻,高并发,那么也只能有一个请求访问数据库。其他线程,要么重试,要么直接返回。

参考

yq.aliyun.com/articles/61…

www.cnblogs.com/rjzheng/p/8…

cloud.tencent.com/developer/a… www.iteye.com/blog/carlos…

tech.meituan.com/2016/12/02/… juejin.cn/post/684490…


learnku.com/articles/28… www.jianshu.com/p/fef1c22d6…

segmentfault.com/a/119000001…