redis缓存击穿问题

系统管理员 2022-12-17 12:58 230阅读 0赞

需要缓存的业务考虑缓存的两种用法模式

1.读模式,如何读取一个数据,应该遵循先从缓存中读取,
如果缓存中没有,再在数据库读取,如果在数据库查到数据则再放到缓存中,并返回
2.写模式,如何保证缓存中的数据和数据库中的数据是一致的
可以使用双写模式或失效模式

  • 双写模式:如果修改数据。如果缓存中有,则可以改完数据库中的数据后,再改缓存中的数据,把缓存中以前的数据覆盖掉
  • 失效模式:改完数据库数据以后,可以把缓存中的数据直接清除掉,可以保证下一次从缓存中拿到的数据是最新的

高并发下的缓存穿透

指查询一个一定不存在的数据,由于缓存是不命中的,将会查询数据库,但是数据库也无此记录,我们没有将这次查询的null写入缓存,这将导致这个不存在的数据每次请求要到DB中去查询,失去了缓存的意义

风险:利用不存在的数据进行攻击,数据库瞬时压力增大,导致崩溃

解决:null结果写入缓存,并加入短暂的过期时间

高并发下的缓存失效问题-缓存雪崩

缓存雪崩是指在我们设置缓存时key采用了相同的过期时间,导致缓存在某一时间同时失效,请求全部转发到DB,DB瞬时压力过重雪崩

解决:原有的失效时间基础上加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间重复率就会降低,就很难引发群体失效的事件

高并发下的缓存失效问题-缓存击穿

对于一些设置了过期时间的key,如果这些key可能会在某些时间点被超高并发的访问,是一种非常热点的数据

如果这些key在大量请求同时进来前正好失效,那么所有对这个key的数据查询都落到db,对缓存造成击穿

解决:加速,大量并发只让一个去查,其他人等待,查询以后释放锁,其他人获取到锁,先查缓存,就会有数据,不用去db

问题1:

setnx占好了锁,业务代码异常或者程序执行过程中宕机,没有执行删除锁的逻辑,就会造成死锁

解决:设置锁的自动过期时间,即使没有删除,会自动删除

问题2:

setnx设置好,正要去设置过期时间,宕机,又死锁了

解决:设置过期时间和占位必须是原子性的,redis支持使用setnx ex命令

问题3:

删除锁直接删除?如果由于业务时间很长,锁自己过期了,我们直接删除,有可能把别人正在持有的锁删除了

结果:占锁的时候,指定锁的名称,每个人只能删除自己的锁

问题4:

如果正好判断是当前值,这个要删除锁的时候,锁已经过期,别人已经设置了新的值,那么我们删除的是别人的锁

解决:删除锁必须保证原子性,使用redis+lua脚本完成

20201026114421735.png

总结:

无论是双写模式还是失效模式,都会导致缓存的不一致问题

1、缓存数据+过期时间足够解决大部分业务对于缓存的要求

2、如果是菜单,商品介绍等基础数据,也可以去使用canal订阅binlog的方式

3、通过加读写锁,写写的时候按顺序排好对,读读无所谓

我们能放入缓存的数据本就不应该是实时性、一致性要求超高的,所以缓存数据的时候加上过期时间,保证每天拿到当前最新的数据即可

我们不应该过度设计,增加系统的复杂性

遇到实时性,一致性要求高的数据,就应该查数据库,即使慢点

发表评论

表情:
评论列表 (有 0 条评论,230人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Redis缓存击穿

    缓存击穿 缓存击穿问题也叫热点Key问题,就是一个被高并发访问并且缓存重建业务较复杂的key突然失效了,无数的请求访问会在瞬间给数据库带来巨大的冲击。 解决方案: 1

    相关 redis缓存击穿问题

    需要缓存的业务考虑缓存的两种用法模式 1.读模式,如何读取一个数据,应该遵循先从缓存中读取,     如果缓存中没有,再在数据库读取,如果在数据库查到数据则再放到缓存