一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第14天,点击查看活动详情。
1. 击穿
当大量并发业务访问Redis获取数据时,由于数据过期已清除,或其他原因数据已经不存在了,而导致大量并发直接访问到数据库。
解决思路:
并发很大,但是要阻止并发到达数据库,redis里又没有key
解决方案:
- 所有有线程都来get key
- 因为key已经不存在了,在得到null的结果后,向缓存中设置值,setnx,这个相当于一把锁,只有在不存在的时候才能设置成功
- 设置成功的,去数据库取数据,并存储到缓存中
- 设置失败的,休眠随机时间后又从第一步开始。随机时间是为了避免又同时去取值。
方案的问题:
1.死锁,第一个线程若是获取数据的时候出现意外,线程挂了。则后边的数据无法拿到锁,而一直休眠。
- 解决方案,拿到锁的时候,设置一个过期时间,在指定时间没返回,锁自动过期。
2.给锁设置过期时间之后,获得锁的线程没挂,但是锁超时了怎么办。
- 解决方案,新建一个线程,监控是否取回数据和线程是否正常,然后去循环检查和更新锁的时间
2 穿透
从业务接受并查询的是数据库根本不存在的数据。并且缓存里也没有。
解决方案:布隆过滤器
布隆过滤器的缺点,只能增加,不能删除
解决方案,在删除数据的时候,设置一个空key,在查到有key但为空的时候,直接返回,不去数据库查询。
3 雪崩
大量的key同时过期,间接造成大量的访问到达数据库。比如设置大量的key为半夜12点过期,此时有大量并发到来,则访问全部到达了数据库。
解决方案:
对于雪崩的问题,解决思路有两种
- 若是数据时点性无关,也就是数据和时间没有关系,则可以设置随即过期时间,避免同时过期。
- 若是时点性相关,比如贷款利率过了12点必须变化,薪资半夜12点调整等,则强依赖击穿方案。
- 或是在业务层,加判断,零点延时。在业务中请求数据的时候判断时间,若是快到12点了前一秒直接延时3秒。此时数据将没有问题。
4 redis做分布式锁
主要就是三点:
- 使用setnx获取锁
- 添加过期时间,避免死锁
- 新建守护线程,检测主线程是否正常并延长锁过期时间