Redis 缓存雪崩、缓存穿透、缓存击穿 解决思考

我们一般用缓存可能会遇到这几个问题:

  1. 数据不一致
  2. 缓存雪崩
  3. 缓存穿透
  4. 缓存并发竞争

为了我们更好解决这些问题,首先我们了解一下概念:

缓存雪崩

问题:

缓存雪崩与缓存击穿不同,缓存雪崩带来的是多个key同时过期,或者redis服务不可用,导致所有的请求全部打到了DB层。

解决方案:

1、建立高可用的Redis集群,使用Cluster加主从的方式,避免单点故障还有全部slot都放到同一个实例上。

2、对于热点数据可以建立本地缓存,即使分布式缓存挂了,也有本地缓存进行兜底。

缓存穿透

问题:

缓存穿透,指的是查询一个不存在的数据,缓存不命中的情况下,DB层查询到的数据又为空,导致Cache层没写缓存。导致请求每次都打到DB层。

解决方案:

1、当查询为空的数据时,缓存的值可以保存一个特殊字符串,比如db_null之类的,并设置一定的过期时间。当下次查询value=db_null的时候,直接就返回空数据了。

        不足:缓存太多空值,占用更多空间。建议设置5分钟缓存

2、增加redis bitmap作为过滤器,如果该ID存在时,则可以进行下一步动作。 

3、增加布隆过滤器(bloomfilter),bloomfilter存储对应的key是否存在,如果该值存在则表示对应的值不为空。

 

缓存击穿

问题:

刚好有热点数据缓存过期了,恰好这个时间内有大量请求进来,在建立缓存之前所有请求打到了DB层,导致持久层可能瞬时被压垮。

解决方案:

1、使用分布式锁,请求发现缓存不在后,去查DB前加入分布式锁,保证有且只有一个去DB层查数据,并更新缓存。

2、手动过期,即所有热点的key不设置缓存过期时间,而是把过期时间放到key的value里面。

具体如下:

  • 获取缓存:通过key获取value的过期时间,判断是否过期,如果未过期,则直接返回。如果已经过期则继续往下执行。
  • 通过后台的一个异步线程去做缓存构建,通过后台的任务去保证有且只有一个线程去查询DB。(可以通过channel去执行,或者消息队列Kafka等方式)
  • 同时,虽然value已经过期了,但是value还是照样返回。这样就能保证服务的可用性,但是同时也损失了一些时效性。

3、Golang里面有个singleflight这个文件,可以使用它保证一个节点里面有且只有一个线程去执行,其他线程则等待该请求线程处理完之后获取到真实数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值