尼恩说在前面
什么是缓存击穿、缓存穿透、缓存雪崩? 缓存击穿、缓存穿透、缓存雪崩 碰到过吗?如何 彻底解决?
最新《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》的PDF,请关注本公众号【技术自由圈】获取,回复:领电子书
本文目录
- 尼恩说在前面:
- CacheAside 模式 —— 使用Redis 缓存常用模式
- 使用Redis 缓存的3大核心问题
- 第一大核心问题:缓存击穿
- 缓存击穿的原因
- 缓存击穿 方案1:加DCL锁更新 缓存
- 缓存击穿 方案2:热点数据,永不过期
- 缓存击穿 方案3:多级缓存 + 热点探测 + 数据预加载
- 第二大核心问题:缓存穿透
- 缓存穿透的原因:
- 缓存穿透的恶果:
- 缓存穿透方案1:缓存空值
-缓存空值的问题:
- 缓存穿透方案2:布隆过滤器
- 布隆过滤器 的问题:
- 第三大核心问题:缓存雪崩
- 缓存雪崩的两大原因
- 缓存雪崩的3大解决方案:
- 设置不同 过期时间 的参考实现:
- 说在最后:有问题找老架构取经
CacheAside 模式 —— 使用Redis 缓存常用模式
先查询 Redis,如果Redis 查询成功,直接返回 如果Redis 查询不存在,去查询 DB; 如果 DB 查询成功,数据回写 Redis,返回 如果 DB 查询不存在,直接返回。
使用Redis 缓存的3大核心问题
缓存击穿(Cache Breakdown): 缓存击穿是指一个备受欢迎的缓存数据突然失效或宕机,导致重建缓存时,由于是热点Key,会有大量的线程来查和重建缓存,导致大量数据请求直接到达数据库,这种我们称为缓存击穿。 缓存穿透(Cache Penetration): 缓存穿透是指查询的Key压根不存在,所以每次都未命中缓存,直接到数据库,这我们称为缓存穿透。 缓存雪崩(Cache Avalanche): 缓存雪崩是指在同一时间段,大量缓存数据同时过期或Redis服务宕机,导致大量请求同时到达数据库,从而给数据库带来非常大的压力。
第一大核心问题:缓存击穿
缓存击穿的原因
缓存击穿 方案1:加DCL锁更新 缓存
加锁检查缓存(第一次检查):当用户请求数据时,首先检查缓存中是否存在该数据。 加锁:如果缓存中没有数据,那么走DB。但是,在尝试从数据库查询数据之前,使用本地锁(或者分布式锁)来确保只有一个请求能够执行数据库查询操作。 数据库查询:如果成功获取到锁,那么第二次检查缓存,如果确实缓存中没有数据, 执行数据库查询操作,获取最新的数据。 更新缓存:将查询到的数据写入缓存,并设置一个合理的过期时间。 释放锁:完成缓存更新后,释放分布式锁,以便其他请求可以继续执行。 返回数据:将查询到的数据返回给用户。 处理其他请求:对于在等待锁释放期间到达的请求,它们可以直接从缓存中获取数据,而不需要再次查询数据库。
//伪代码
public object GetProductListNew() {
int cacheTime = 30;
String cacheKey ="product_list";
String ockKey = cacheKey;
String cacheValue = CacheHelper.get(cacheKey);//第一次检查
if (cacheValue != null) {
return cacheValue!
}else {
synchronized(lockKey) cacheValue = CacheHelper.get(cacheKey); //第二次检查
if (cacheValue != null){
return cacheValue;
}else {
//这里一般是sql查询数据
cacheValue = GetProductListFromDB();
CacheHelper.Add(cacheKey,cacheValue, cacheTime);
}
}
return cacheValue;
}
}
缓存击穿 方案2:热点数据,永不过期
要值得注意的是,这里说到的永不过期并不是将热点数据存在时间设置为无限制。而是将过期时间存在key对应的value里,如果发现要过期了,通过一个后台的异步线程进行缓存的重建。
缓存击穿 方案3:多级缓存 + 热点探测 + 数据预加载
第二大核心问题:缓存穿透
缓存穿透的原因:
缓存穿透的恶果:
缓存穿透方案1:缓存空值
缓存空值的问题:
缓存穿透方案2:布隆过滤器
布隆过滤器 的问题:
第三大核心问题:缓存雪崩
缓存全盘宕机,缓存挂了, 大量key在同一时间过期
缓存雪崩的两大原因
缓存全盘宕机,缓存挂了, 大量key在同一时间过期
缓存雪崩的3大解决方案:
提高缓存可用性
集群部署:通过集群来提升缓存的可用性,可以利用Redis本身的Redis Cluster或者第三方集群方案如Codis等。 多级缓存:设置多级缓存,设置一级缓存本地 guava 缓存,第一级缓存失效的基础上再访问二级缓存 redis,每一级缓存的失效时间都不同。
过期时间
设置不同的过期时间:过期时间随机值。为了避免大量的缓存在同一时间过期,可以把不同的 key 过期时间随机生成,避免过期时间太过集中。 热点数据永不过期。
熔断降级
限流:如果redis宕机,可以限流,避免同时刻大量请求打崩DB 熔断:当缓存服务器宕机或超时响应时,为了防止整个系统出现雪崩,可以使用hystrix 类似的熔断,暂时停止业务服务访问db, 或者其他被依赖的服务,避免 MySQL 被打死。 降级:当出现大量缓存失效,而且处在高并发高负荷的情况下,在业务系统内部暂时舍弃对一些非核心的接口和数据的请求,而直接返回一个提前准备好的 fallback(退路)错误处理信息。
设置不同 过期时间 的参考实现:
// 缓存原本的失效时间
int exTime = 10 * 60;
// 随机数生成类
Random random = new Random();
// 缓存设置
jedis.setex(cacheKey, exTime + random.nextInt(1000) , value);
说在最后:有问题找老架构取经
被裁之后, 空窗1年/空窗2年, 如何 起死回生 ?
案例1:42岁被裁2年,天快塌了,急救1个月,拿到开发经理offer,起死回生
案例2:35岁被裁6个月, 职业绝望,转架构急救上岸,DDD和3高项目太重要了
案例3:失业15个月,学习40天拿offer, 绝境翻盘,如何实现?
被裁之后,100W 年薪 到手, 如何 人生逆袭?
100W案例,100W年薪的底层逻辑是什么? 如何实现年薪百万? 如何远离 中年危机?
如何 逆天改命,包含AI、大数据、golang、Java 等
实现职业转型,极速上岸
关注职业救助站公众号,获取每天职业干货
助您实现职业转型、职业升级、极速上岸
---------------------------------
实现架构转型,再无中年危机
关注技术自由圈公众号,获取每天技术千货
一起成为牛逼的未来超级架构师
几十篇架构笔记、5000页面试宝典、20个技术圣经
请加尼恩个人微信 免费拿走
暗号,请在 公众号后台 发送消息:领电子书
如有收获,请点击底部的"在看"和"赞",谢谢