导读
使用Redis难免会遇到Redis缓存穿透,缓存击穿,缓存雪崩,热点Key的问题。有些同学可能只是会用Redis来存取,基本都是用项目里封装的工具类来操作。但是作为开发,我们使用Redis时可能会遇到上述问题,可能你还不知道这几个名词是什么意思,那么现在就让我们一起来探讨下吧。
首先我们使用Redis的逻辑是这样的:
即:先从缓存取,缓存有就直接返回,没有就查库,查到就存Redis里,没有返回空。
在实际使用Redis的时候一定会遇到缓存穿透、缓存击穿、缓存雪崩和热点key的问题,这几个概念是什么?对应的怎么解决?一起来看下。
缓存穿透
是针对数据库和缓存中都没有的数据。场景:当客户端发起查询时,缓存中没有就会去查库,库里也没有,就会返回给客户端错误信息。这样是没问题的,看起来逻辑是完美的,但是这里存在一个漏洞,那就是无论什么样的Key过来查,我们都去接受它的请求,这就可能会被黑客抓住,发起大量请求,并且Key都是我们系统中没有的,库里也查不到对应的值,这样的Key称之为非法Key。那么当大量这样的请求过来时是不是都不会命中Redis,然后都会打到DB上,当DB瞬时接收到如此多的连接时,DB就有可能撑不住,挂掉。这就是存在的一个隐藏的漏洞,黑客或者恶意攻击者就会抓住这一点攻击你的系统,使你的系统瘫痪。
实际开发中就要考虑到这一点,可以在系统层面加一层过滤,将系统认为非法的key进行一次拦截,直接返回给客户端错误信息。具体这层过滤怎么加,哪些是非法Key要根据实际的业务逻辑来定,这里只给出解决思路。
缓存击穿
是针对缓存中没有但数据库有的数据。场景是,当Key失效后,假如瞬间突然涌入大量的请求,来请求同一个Key,这些请求不会命中Redis,都会请求到DB,导致数据库压力过大,甚至扛不住,挂掉。
这个问题的解决办法就是:
1、设置热点Key,自动检测热点Key,将热点Key的过期时间加大或者设置为永不过期,或者设置为逻辑上永不过期,具体设置方法待会说。
2、加互斥锁。当发现没有命中Redis,去查数据库的时候,在执行更新缓存的操作上加锁,谁拿到锁谁去更新,同时在拿到锁之后先从缓存再获取一次如果有就返回,没有就查库然后更新。(双重校验)
缓存雪崩
是指大量Key同时失效,对这些Key的请求又会打到DB上,同样会导致数据库压力过大甚至挂掉。
这个问题的解决办法就是,让Key的失效时间分散开,可以在统一的失效时间上再加一个随机值,或者使用更高级的算法分散失效时间。
热点Key问题
针对热点数据,我们可以设置热点Key的过期时间很大,或者在逻辑上永不过期。啥意思呢?
意思就是说,假如我们设置热点数据过期时间为24小时,那么我们可以使用监听器去监听这热点数据,当检测到它快要过期时,异步起个线程去更新这个热点数据。可以达到逻辑上永不过期的效果。
另外一点,我们要有热点数据自动检测机制。即有个监控平台,来监控每个key某个时间段的请求次数,过期次数,查库次数,来分析这个key是不是热点数据,当达到某阈值时将key升级为热点key,然后走热点数据的逻辑。
这里只提供思路,具体怎么实现不再赘述。如果有更好的办法,欢迎留言交流。