在生产环境中,除了遇到数据不一致,还有三种缓存异常的问题也经常遇到,分别是缓存穿透、缓存击穿和缓存雪崩。这三个问题一旦发生,会导致大量的请求积压到数据库层。如果并发量大的话,就会导致数据库负载增大,使缓存的作用降低。
一、缓存穿透
1. 缓存穿透的理解
缓存穿透是查询一个不存在的数据,缓存和数据库都无法命中,如果数据库查询不到数据则不会写入到缓存中,这将会导致这个不存在的数据每次请求都要到数据库去查询,失去了缓存保存的意义,如果请求量大的话,可能会导致数据库宕机或是故障。
示意图:
造成缓存穿透的基本原因有两种。第一,自身业务代码或者数据出现问题(例如:set 和 get 的key不一致),第二,受到一些恶意攻击、爬虫等造成大量空命中。
2.解决方案
2.1 缓存空值
缓存空值:是指在数据库没有命中的情况,对查询的key进行缓存空值(key,null)。
缓存空值会产生两个问题:
①:value为null也会占用空间,空值做了缓存,代表缓存中有了更多的键,占用了存储空间也增大了维护难度,比较有效的方式是在存储这类数据时可以设置一个较短的过期时间,让其自动删除。
②:缓存和数据库的数据会有一段时间的不一致,可能会对业务有一定影响。例如过期时间设置为5分钟,如果此时数据库中添加了这个数据,那此段时间就会出现缓存层和存储层数据的不一致,此时可以利用消息系统或者其他方式更新缓存中的空值。
2.2 布隆过滤器拦截
在访问缓存和数据库之前,将存在的key用布隆过滤器提前保存起来,做第一层拦截,当收到一个对key请求时先用布隆过滤器验证是key否存在,如果存在在进入缓存、数据库。可以使用Redisson做布隆过滤器。
布隆过滤器的算法原理:
它的底层主要是先去初始化一个比较大数组,里面存放的二进制0或1。在一开始都是0,当一个key来了之后经过3次hash计算,模于数组长度找到数据的下标然后把数组中原来的0改为1,这样的话,三个数组的位置就能标明一个key的存在。查找的过程也是一样的。
当然是有缺点的,布隆过滤器有可能会产生一定的误判,我们一般可以设置这个误判率,大概不会超过5%,其实这个误判是必然存在的,要不就得增加数组的长度,其实已经算是很划分了,5%以内的误判率一般的项目也能接受,不至于高并发下压倒数据库。
二、缓存击穿
1. 缓存击穿的理解
缓存击穿意思是指当一个热点key(例如:一场秒杀活动中),并发量很大。当前热点key缓存在某个时间点过期,此时有大量并发请求访问热点key,查询缓存已经过期未命中,并发请求都发送到数据库,导致数据库负载过大,甚至使数据库宕机或是故障。
2.解决方案
2.1 分布式互斥锁
当缓存失效时,并发请求进来时允许其中一个线程不立即去load db,先使用如 Redis 的 setnx 去设置一个互斥锁,当操作成功返回时再进行 load db的操作并回设缓存,否则重试get缓存的方法,其他线程则处于等待阶段,等这个线程回设缓存成功后然后从缓存中获取数据返回即可
2.1 设置逻辑过期key
①:在设置key的时候,设置一个过期时间字段一块存入缓存中,不给当前key设置过期时间
②:当查询的时候,从redis取出数据后判断时间是否过期
③:如果过期则开通另外一个线程进行数据同步,当前线程正常返回数据,这个数据不是最新
3.两种方案各有利弊
①:如果选择数据的强一致性,建议使用分布式锁的方案,性能上可能没那么高,锁需要等待,也有可能产生死锁的问题。
②:如果选择key的逻辑删除,则优先考虑的高可用性,性能比较高,但是数据同步这块做不到强一致。
三、缓存雪崩
1. 缓存雪崩的理解
缓存在一段时间内集体过期或者失效(也可能是redis宕机),发生大量的缓存击穿,所有的查询都落在数据库上,造成了缓存雪崩,数据库负载过大,导致数据库宕机或是故障。
缓存雪崩没有完美解决方案,尽量让失效时间点分散开,比如可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。
2.解决方案
2.1 缓存高可靠集群:
可以把缓存层设计成高可用的集群,即使个别节点、个别机器、甚至是机房宕掉,依然可以提供服务。
2.2 做二级缓存,或者双缓存策略:
采用多级缓存,本地进程作为一级缓存,redis作为二级缓存,不同级别的缓存设置的超时时间不同,即使某级缓存过期了,也有其他级别缓存兜底。
2.3 数据预热:
可以通过缓存reload机制,预先去更新缓存,再即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。
2.4 服务熔断或请求限流机制
在缓存失效后,通过服务熔断机制,暂停业务应用对缓存服务的访问,从而降低对数据库的访问压力。或者请求限流,我们在业务系统的请求入口前端控制每秒进入系统的请求数,避免过多的请求被发送到数据库。我们使用这两个机制,来降低雪崩对数据库和整个业务系统的影响。
评论区