缓存常见问题解决方案

一、热点key

这里先只讨论 read 热点,这里的缓存媒介使用 redis。
若发生在write 操作上:1 这种场景比较少见(一般在设计早期就提前考虑了),2 笔者暂未想到较好的解决方案。有兴趣的同学可以一起留言探讨。

由于某突发事件导致缓存中某些 key 访问大幅度增高,可能达到 redis 的QPS极限,若不及时处理可能导致更糟糕的问题出现(比如 击穿、雪崩等)。 (其实就是 read 流量猛增,与分不分片没多大关系)。

实际场景:热门促销商品、突发的娱乐圈热点头条问题,访问量会迅速飙升。

解决方案

方式1:增加 Slave(readOnly)。

请求流量通过LBS分发到Proxy层,Proxy层分发读写。如下图,read流量全部打到可横向扩展的readOnly上,解决了read 热点压力问题。
更进一步优化:可以在Proxy层做Local Cache,对最近Interval(interval长短视业务场景而定)内的访问量最高的TOP N key进行缓存(注意:Interval不是local cache的时长)。
在这里插入图片描述

方式2:虚拟子key

写缓存时把 key 通过一定策略构建成三个(分片数)子 key,这样每个分片上都有这个数据。读的时候使用同样策略构建子 key,并通过一定负载均衡策略(最简单的:随机)选择一个子key进行访问。
在这里插入图片描述

二、击穿

实际场景1:大量恶意访问数据库中不存在的key(这种情况下缓存中肯定也不存在),击穿缓存,直接访问数据库。

解决方案

当访问到这种 key时,把 key 加载缓存并设定过期时间,value 可设定默认值或者空值。这样就不至于完全击穿,大量流量打到DB上去。

实际场景2:同时有大量热点 key 缓存同时过期,(高并发场景下)大量请求会涌向数据库。

解决方案

方案1:这种情况可以对 key 的缓存时长在一个标准值的基础上做随机偏移,这样基本上能够把过期时长散列开。
方案2:当击穿时,针对 key 做分布式锁竞争,去DB加载数据。这种方式可能会导致客户端因为竞争锁堆积大量请求。当然竞争锁失败也没必要等待可直接返回友好提示语(毕竟这种突发状况不是常态)。
在这里插入图片描述

TODO …

猜你喜欢

转载自blog.csdn.net/weixin_40854155/article/details/87486006