redis缓存穿透、击穿、雪崩
缓存穿透、击穿、雪崩
原文:https://mp.weixin.qq.com/s/_sqGyTvMphOLPpbSCLh0Yw
总结,请求绕过redis,直接作用到mysql上
雪崩:key大面积失效(定时任务刷新缓存,key的过期时间相同,某个时间点全部失效)
解决方案:失效时间都加个随机值避免同一时间大面积失效
场景:app首页数据,所有首页的Key失效时间都是12小时,中午12点刷新的,我零点有个秒杀活动大量用户涌入,假设当时每秒 6000 个请求,本来缓存在可以扛住每秒 5000 个请求,但是缓存当时所有的Key都失效了。此时 1 秒 6000 个请求全部落数据库,数据库必然扛不住
穿透:用户恶意使用不存在的key,则请求会到达数据库(如果这个用户并发一直请求就会。。)
解决方案:代码层做好数据效验
场景:使用不存在的用户id,如-1,请求接口
击穿:一个Key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个Key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库
解决:将key设置成永不过期,或者自动续期
解决方案二:如果缓存必须更新,加锁,代码加锁后,10万请求,只有一个进入先判断缓存不再,就查询数据库,并更新缓存,接下来释放锁,其他请求就能进来了,并且不需要查询数据库
这个锁最好使用redission分布式锁
分布式锁(官方推荐redisson)
maven
<!-- https://mvnrepository.com/artifact/org.redisson/redisson --> <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.12.5</version> </dependency>
springboot项目
<!-- https://mvnrepository.com/artifact/org.redisson/redisson-spring-boot-starter --> <dependency> <groupId>org.redisson</groupId> <artifactId>redisson-spring-boot-starter</artifactId> <version>3.12.5</version> </dependency>
redisson官方中文文档
https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95
redis实现
key是k,value是v
命令行
#NX是不存在才设置值(原子性的操作),ex是存在才设置值
set k v NX
代码
问题1:执行业务时出现异常(或者断电导致服务停止)未执行删除锁操作,导致死锁。之后的所有请求都进不来
解决:加锁的同时设置锁的过期时间(不同时进行还是会死锁,可能加完锁还没设置过期时间断电导致)
问题2:业务执行时间过长,导致锁过期,下一个请求进来之后正执行业务时,第一个线程业务执行完毕,将前一个的锁删除掉了
解决:加锁时,加上唯一ID去标示值(但是判断是否是自己的锁和删除锁必须同时执行,否则删除锁时,当前线程的锁失效了,下一个线程锁上了,就把下一个锁给删除了)
但是这个原子操作需要写脚本!!