在大型项目中,为了减小数据库的负载压力,经常将一些热点数据存到redis缓存中,这样在获取数据是从redis缓存中去取,可以有效的缓解数据库压力,但是由于缓存过期,会造成一些意外情况,给数据库带来灾难性的压力,最常见的几种情况是缓存击穿、缓存穿透、缓存雪崩,下面聊一下这几种情况的场景和相应的解决方案:
1、缓存击穿:
(1)现象说明: 某 个热点数据存到redis中,key在某一时刻过期,恰好在这一瞬间大量的请求打过来,由于redis里缓存数据不存在,请求直接打到DB数据库,造成数据库压力过大,造成宕机,具体的应用场景比如秒杀抢购商品。
(2)应对措施:在查询数据库的时候加上锁(单体服务家线程锁、分布式服务分布式锁),这样在缓存过期的瞬间只有一个线程能抢到锁,去查询数据库并把缓存续上,其他的请求依旧从redis缓存中获取数据。
2、缓存雪崩:
(1)现象说明:redis缓存的数据设置了相同的过期时间,在某个时刻redis缓存过期,恰好在这一瞬间,大量的请求发送过来,直接打到数据库DB,造成数据库宕机
(2)应对措施:缓存key的过期时间设置为随机数、定时器定时刷新缓存
3、缓存穿透:
(1)现象说明:缓存击穿和缓存雪崩都是由于key过期造成,与他们不同的是缓存穿透是对一个不存的key进行恶意攻击,请求不断的绕过redis打到数据库,比如数据的自增主键是整数,黑客会利用这一特点寻找漏洞,使用负数的id不断请求,恶意攻击数据库
(2)应对措施:对不存在的key直接返回null不去查询数据库、ip白名单、布隆过滤器。
布隆过滤器是应对缓存穿透的一种有效手段,java里可以使用redission或者google的guava里写好bloomfilter工具