redis缓存穿透、缓存雪崩、缓存击穿、并发竞争

关注微信公众号“虾米聊吧”,每天更新一篇技术文章,文章内容涵盖架构师成长必经之路应掌握的技术,一起学习,一起交流。

 

缓存穿透、缓存雪崩、缓存击穿、并发竞争是缓存最常见的几个问题,接下来我们简单谈谈关于这他们的出现场景以及可能的解决方案都有哪些?

 

**缓存穿透**

概念:是指查询一个不存在的数据,由于缓存无法命中,该请求将去查询数据库,但是数据库也无此记录,并且出于容错考虑,我们没有将这次查询的null写入缓存,这将导致这个不存在的数据每次请求都要到数据存储层(比如mysql)去查询,导致缓存失去了意义。如果在流量大的时候可能还会导致我们的数据库服务直接挂掉,而且要是有人利用不存在的key频繁攻击我们的应用,那这就成了我们系统的一个漏洞

解决:其实我们可以对空结果集也进行缓存,比如将该空结果集缓存为unknow,这样缓存就会命中,减少db的访问压力,但需要把它的过期时间设置很短,最长不超过五分钟。

 

**缓存雪崩**

概念:是指缓存中大批量数据到期,在某一时刻同时失效(可能是由于我们设置缓存时采用了相同的过期时间),而查询量巨大,此时请求将全部转发到DB,导致DB因无法承受如此大的瞬时压力而雪崩。

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

 

**缓存击穿**

概念:是指对于一些设置了过期时间的key,如果这些key可能会在某些时间点被超高并发地访问,是一种非常“热点”的数据。这个时候,需要考虑一个问题:如果这个key在大量请求同时进来之前正好失效,那么所有对这个key的数据查询都落到db,我们称为缓存击穿。

解决:加锁(分布式锁);对该热点key进行加锁,只允许加锁成功的当前请求直接访问db,等待当前请求访问完成并且写入redis后释放锁,那么后续的等待的大量请求就会直接走缓存了,这样将大大降低db的访问压力。

 

缓存击穿与缓存雪崩的区别:

1. 击穿是一个热点key失效

2. 雪崩是很多key集体失效

 

**redis并发竞争问题**

所谓redis的并发竞争问题是指多个客户端同时并发写同一个key,可能本来应该先写的数据后写了,产生了顺序不一致从而导致数据版本错乱了。或者是多个客户端同时获取同一个key,修改值后再写回去,如果这个写的顺序错了,那么最终获取的数据就错了。

比如多个客户端同时写一个key,初始值为A,本来需要按顺序依次修改为B、C、D,最后的结果为D,但是可能在并发写的时候顺序变了比如变成了C、D、B,那么最终的结果就成了B,然鹅,这并不是我们想要的结果。

 

那么我们怎么来解决这个问题呢?常用的有如下两种方案:1.分布式锁+版本号(时间戳)   2.消息队列MQ

 

1.分布式锁+版本号(时间戳)

分布式锁这里就不多做介绍了,即谁抢到了锁谁就可以操作该key,其目的就是保证同一时刻只有一个线程来操作key。

时间戳的目的就是为了做一个标识,即每个数据都携带一个时间戳,

比如:A:12:00 、 B:12:01、C:12:02、D:12:03,假如B先抢到锁,设置了key的值,并且数据时间为12.01,后面A抢到锁,和现有key中的值一对比发现自己数据的时间早于缓存中数据时间戳(12:00<12:01),那么此时A就不做任何操作了。

redis缓存穿透、缓存雪崩、缓存击穿、并发竞争_第1张图片

 

2.消息队列MQ的方式:

在并发量过大的情况下,可以通过消息中间件进行处理,把并行读写进行串行化。

即把所有操作都放在队列中使其串行化一个一个执行这样就可以保证执行的顺序性了

这种方式在一些高并发的场景中是一种通用的解决方案。

 

关注微信公众号“虾米聊吧”,获取更多知识资料干货~,一起交流,一起学习~,

一起打卡学习,一起交流进步吧!

微信扫描二维码,关注我的公众号

你可能感兴趣的:(架构,redis)