Redis-缓存穿透、缓存击穿、缓存雪崩
Redis之缓存穿透、缓存击穿、缓存雪崩
缓存穿透
在说明缓存穿透前,简单说说redis。
- Redis的作用: Redis在内存中缓存数据库数据,在面对大量数据请求时,进行拦截,通过缓存提高数据访问效率,减轻数据库压力。
本质
缓存穿透本质上就是让Redis失去作用,退化为数据库请求。
用户频繁大量请求根本不存在的数据(redis缓存、mysql数据库中都没有的数据)。这样导致的结果就是:
- redis在内存缓存查询是否存在,不存在(可能是没缓存或者没有,redis不知道)则进行数据库查询。
- 正常如果数据存在,则将数据进行缓存,下次访问时在通过缓存返回
- 但是现在是一个不存在的数据,这样相当于就是做了一个数据库查询,通过频繁大量进行这些不存在数据的请求,就导致redis失去作用,像是被无视穿透了一样,直接变成了数据库查询请求。
解决方案
- 业务层校验
对请求参数进行校验,明确错误参数直接拦截返回。
局限:只能对一些简单的具有明显错误的数据查询进行拦截。
如:请求参数为主键自增id,那么id<0的明显错误参数直接拦截返回错误。
- 不存在数据设置短过期时间
对数据查询结果为空的数据,对空结果进行缓存,设置短的过期时间(如30s)
局限:起一定缓解作用 - 布隆过滤器
布隆过滤器是一种数据结构,利用极小的内存,可以判断大量的数据“一定不存在或者可能存在”。
在写入数据库数据时,使用布隆过滤器做个标记,然后用户发起请求后,判断请求值是否存 在于布隆过滤器,如果不存在 那这个请求直接无效,如果存在 那就在缓存中查找对应的数据。这样当出现大量请求的时候,会先查询布隆过滤器和Redis,不会对数据库造成压力。
布隆过滤器
缓存击穿
本质
通过卡好时机,利用redis的缓存机制,击穿redis保护下的数据库。
就是在redis中一个热点key失效的同时,对这个热点key发起大量请求,从而全部到达数据库,压垮数据库。
解决方案
- 暴力设置热点数据永不过期
- 定时更新:过期时间1h,每次到达59minute时,定时任务更新,重新设置过期时间为1h
- 互斥锁
互斥锁简单来说就是在Redis中根据key获得的value值为空时,先锁上,然后从数据库加载,加载完毕,释放锁。若其他线程也在请求该key时,发现获取锁失败,则睡眠一段时间(比如100ms)后重试。
缓存雪崩
本质
缓存雪崩形成的两种原因:
- 缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
- Redis 故障宕机

解决方案
- 缓存过期的解决方案
- 缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
- 如果缓存数据库是分布式部署,将热点数据均匀分布在不同搞得缓存数据库中。
- 设置热点数据永远不过期。
- 互斥锁
发现访问的数据不在Redis中,加上互斥锁,保证同一时间内只有一个请求来构建缓存( 从数据库读取数据,再将数据更新到 Redis 里),当缓存构建完成后,再释放锁。未能获取互斥锁的请求,要么等待锁释放后重新读取缓存,要么就返回空值或者默认值。
实现互斥锁的时候,最好设置超时时间,不然第一个请求拿到了锁,然后这个请求发生了某种意外而一直阻塞,一直不释放锁,这时 其他请求也一直拿不到锁,整个系统就会出现无响应的现象。
- Redis故障宕机的解决方案
- 服务熔断或请求限流机制
- 启动 服务熔断 机制,暂停业务应用对缓存服务的访问,直接返回错误,暂停使用数据库,等Redis恢复正常后,在允许业务应用缓存服务
- 启动 请求限流 机制,只将少部分请求发送到数据库进行处理,再多的请求就在入口直接拒绝服务。
- 构建Redis缓存高可靠集群
参考文章

浙公网安备 33010602011771号