数据库的数据存储在磁盘中,而磁盘的读写速度很慢,为了提高数据访问的性能,采用内存数据库Redis作为缓存层,这样可以大大提高性能。
一、缓存雪崩
当大量缓存数据同时过期或者Redis故障宕机时,如果此时有大量用户请求,都无法在Redis中处理,于是全部请求都直接访问数据库,从而导致数据库压力剧增,严重导致数据库宕机。
产生原因:
大量数据同时过期;Redis故障宕机。
解决方案:
1、针对大量数据同时过期的解决方案
- 均匀设置过期时间,避免将大量数据设置成同一过期时间,可以给过期时间加一个随机数。
- 互斥锁,当一个请求发现数据不在Redis中,加一个互斥锁,保证同一时间只有一个请求构建缓存(从数据库读取数据,再更新到Redis中),构建完成后在释放锁。未获取锁的请求,要么等待锁释放,要么返回空值。
- 双key策略,在缓存中使用两个key,一个主key设置过期时间,一个备key不设置,当访问不到主key的数据,直接返回备key的数据。
- 后台更新缓存,业务线程不再负责更新缓存,缓存也不设置有效期,而是让缓存“永久有效”,并将更新缓存的工作交由后台线程定时更新。
2、针对Redis故障宕机解决方案
- 服务熔断或请求限流机制,启动服务熔断机制,暂停业务应用对缓存服务的访问,直接返回错误,不用再继续访问数据库,全部业务都无法正常工作。请求限流是将少部分请求发送到数据库进行处理,再多的请求在入口直接拒绝服务,可以减少对业务的影响。
- 构建Redis缓存高可靠集群,通过主从节点的方式构建Redis缓存高可靠集群,当主节点发生故障,从节点可以切换成主节点,继续提供缓存服务。
二、缓存击穿
可以看成缓存雪崩的子集,如果缓存中某个热点数据过期,此时大量请求访问该热点数据,就无法从缓存中读取,直接访问数据库,给数据库造成巨大压力。
产生原因:
热电数据过期
解决方案:
1、互斥锁方案
2、后台更新缓存
三、缓存穿透
当用户访问的数据,既不在缓存中,也不在数据库中,导致请求在访问缓存时,发现缓存缺失,再去访问数据库,发现数据库中也没有要访问的数据,没办法构建缓存数据来服务后续请求。那么当大量这样的请求到来时,数据库压力剧增。
产生原因:
访问的数据既不在缓存中,也不在数据库中。通常是业务误操作或者黑客恶意攻击导致缓存穿透。
解决方案:
1、限制非法请求,判断是恶意请求就返回错误。
2、缓存空值或者默认值,当发现缓存穿透的现象时,针对查询的数据,在缓存设置空值或默认值
3、使用布隆过滤器快速判断数据是否存在,避免通过数据库查询数据是否存在。当数据写入数据库,使用布隆过滤器做个标记。
注:布隆过滤器是通过N个哈希函数对数据进行哈希运算,再利用一个初始值都为0的数组,通过N个哈希值对数组长度进行取模,得到的值为数组下标,将这些下标对应的值设置为1。当查询数据是否在数据库中,只需要看数组对应的下标是否全为1。