Redis缓存雪崩,缓存穿透,缓存击穿总结

104 阅读3分钟

缓存穿透

定义

指查询一个数据库不存在的数据。

比如说,一个用户的基本信息(缓存key为uid)或订单的信息(缓存key为order_id),缓存或数据库里都没有这个uid或order_id的信息,但是如果有请求要获取这个信息,那么逻辑处理时就会跨过缓存这一层去查数据库,如果这样的请求短时间内非常多可能会压垮数据库。

解决方案

  • 给不存在的Key赋值默认的空置,并且设置较短的缓存时间,比如60秒。
  • 布隆过滤器,将数据库中的key全部建立到布隆过滤器中, 每次请求先查询布隆过滤器
  • 接口层增加校验,不合法的参数直接return,比如一个ID永远不会小于0,对于小于0的ID参数直接Return

缓存雪崩

定义

缓存中数据大批量同一时间过期,而查询数据量巨大,引起数据库压力过大甚至宕机。

比如,马上就要到双十一零点,很快就会迎来一波抢购,这波商品时间比较集中的放入了缓存,假设缓存两个小时。那么到了凌晨二点钟的时候,这批商品的缓存就都过期了。而对这批商品的访问查询,都落到了数据库上,对于数据库而言,就会产生周期性的压力波峰。

其实集中过期,倒不是非常致命,比较致命的缓存雪崩,是缓存服务器某个节点宕机或断网。因为自然形成的缓存雪崩,一定是在某个时间段集中创建缓存,那么那个时候数据库能顶住压力,这个时候,数据库也是可以顶住压力的,无非就是对数据库产生周期性的压力而已。但是缓存服务节点的宕机,对数据库服务器造成的压力是不可预知的,很有可能瞬间就把数据库压垮,所以,这个时候需要用到高可用的Redis cluster。

解决方案

  • 集中设置的缓存key,为缓存失效时间设置一个随机因子
  • 避免因为宕机原因造成的缓存雪崩,采用高可用的Redis Cluster模式

缓存击穿

定义

一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。

比如说,订单的信息(缓存key为order_id)在缓存中有过期时间,如果在特定的时间这个订单信息在缓存中已经过期但是尚未从数据库查出最新的信息set到缓存上,恰好这个时候大并发请求过来了,那么这些请求的逻辑处理也会跨过缓存直接查询数据库,这个大并发的查询可能会压垮数据库。

解决方案

  • 加分布式锁或者分布式队列:用加分布式锁或者分布式队列的方式保证缓存的单线程写,从而避免失效时大量的并发请求落到底层存储系统上。在加锁方法内先从缓存中再获取一次(防止另外的线程优先获取锁已经写入了缓存),没有再查DB写入缓存。 (当然也可以: 在没有获取锁的线程中一直轮询缓存,至超时)
  • 添加超时标记:在缓存的对象上增加一个属性来标识超时时间,当获取到数据后,校验数据内部的标记时间,判定是否快超时了,如果是,异步发起一个线程(控制好并发)去主动更新该缓存。
  • 热点数据要求实时性比较低,设置热点数据永不过期或在热点时段不过期,在访问低峰期过期。