非关系型数据库 八股文 Redis相关 缓存雪崩 击穿 穿透

目录

缓存雪崩

大量数据同时过期解决方案

[也有可能是 Redis 挂了 故障](#也有可能是 Redis 挂了 故障)

缓存击穿

用互斥锁解决

热点数据永远不过期

[缓存穿透 重点](#缓存穿透 重点)

可能的原因

[限制 请求的 访问](#限制 请求的 访问)

缓存空值或者默认值

布隆过滤器(重要)

总结

参考资料


缓存雪崩

缓存雪崩是指大量缓存数据同时过期

所以我们通常会给 redis 里面的数据随机化过期时间 当缓存数据过期后 用户请求数据 数据不在缓存里 就会重新生成缓存 后续的请求就能直接访问缓存

如果数据大规模过期 用户请求就会全去 mysql mysql 承受不了就会宕机 进而导致整个系统崩溃

redis 故障也会导致缓存雪崩

大量请求也会到 mysql 去

大量数据同时过期解决方案

  1. 随机化过期时间

设置缓存数据过期时间随机 用 伪随机数 设置时间

  1. 互斥锁

互斥锁 这个做法是如果发现 redis 没有数据 加一个互斥锁 则在同一时间内 只让一个线程去构建缓存 这样就不用所有请求都到 mysql 了 当这个线程构建缓存结束后 释放锁 其他线程的请求此时就会进来 获取新的缓存

  1. 异步处理

可以让缓存一直存在 即使过期了 也很快更新 我们可以设置一个定时任务 在后台检测缓存是否存在 如果不存在则更新 尽量保证每次用户访问数据的时候 缓存都是存在的 同样的我们也可以使用消息队列 业务线程发现缓存失效 通过消息队列发一条消息通知后台线程更新缓存

  1. 缓存预热

我们在业务上线的时候 最好进行缓存预热 先把缓存加载起来

也有可能是 Redis 挂了 故障

  1. 服务熔断 请求限流

redis 挂了则直接返回错误 不要访问数据库 但这样会让业务无法工作

限流也可以 请求太多了就直接拒绝服务 直到正常

  1. 构建集群

构建 redis 集群

缓存击穿

假设我们有热点数据

在高并发场景下获取热点数据

热点数据过期的一瞬间 大量高并发请求会直接到 mysql

然后系统就挂了

我感觉缓存击穿是缓存雪崩的一个子集

用互斥锁解决

还是在业务线程请求数据的时候 如果发现缓存里没有数据 就加上互斥锁 保证此时间只有业务线程去数据库获取数据再回来更新缓存 然后释放锁 让其他线程去拿缓存里的数据

如果未能拿到互斥锁的请求 要不返回空值 要不继续等

热点数据永远不过期

永不过期

如果数据库数据更新了再通知缓存

可以用消息队列实现

缓存穿透 重点

之前我们说的是 缓存雪崩 缓存击穿 这两种情况

那么说明还是有数据的 我们只是要求缓存恢复相对应的数据 即可正常运行

但是如果 数据库没有数据 缓存也没有数据

后续的请求依旧会全部到达缓存 导致数据库压力骤增

为什么会存在 数据库中也没有数据 缓存中也没有数据这种情况呢

可能的原因

  1. 业务误操作 删掉了 mysql 和缓存里面的数据
  2. 黑客恶意攻击 特地访问不存在的数据

限制 请求的 访问

在 API 的入口处我们要判断请求参数是否合理

请求参数是否包含非法值 是否存在

让恶意请求不会到达数据库和缓存 直接被拦截

缓存空值或者默认值

当我们线上业务发现存在缓存穿透

可以在缓存里面提前设置一个空值或者是默认值

这样后续请求到达缓存的时候就能读取空值或者默认值 返回给应用

而不会继续查询数据库

布隆过滤器(重要)

布隆过滤器是一个位数组

通过 k 个函数对数据进行哈希计算

得到 k 个结果

然后将结果作为索引

将对应索引处的值标记为 1

数据传入同样是进行 k 个哈希运算

如果这 k 个位置的数值都是 1 那么表示数据已经出现过了

布隆过滤器主要反馈的是两个信息

  1. 数据可能出现过 (因为可能会存在哈希冲突)
  2. 数据一定没有出现

布隆过滤器说数据存在 可能存在 也可能不存在

但是布隆过滤器说数据不存在 那就是不存在

进入缓存查数据的时候 在要进入数据库查询数据返回更新缓存的时候 我们可以使用布隆过滤器查看数据库中是否存在数据

总结

参考资料

什么是缓存雪崩、击穿、穿透? | 小林coding

相关推荐
席万里几秒前
Go语言企业级项目使用dlv调试
服务器·开发语言·golang
孔令飞2 分钟前
使用 Go 与 Redis Streams 构建可靠的事件驱动系统
redis·ai·云原生·golang·kubernetes
jerry60918 分钟前
c++流对象
开发语言·c++·算法
yuanlaile18 分钟前
Go全栈_Golang、Gin实战、Gorm实战、Go_Socket、Redis、Elasticsearch、微服务、K8s、RabbitMQ全家桶
linux·redis·golang·k8s·rabbitmq·gin
fmdpenny18 分钟前
用python写一个相机选型的简易程序
开发语言·python·数码相机
极客智谷20 分钟前
深入理解Java线程池:从原理到实战的完整指南
java·后端
高效匠人26 分钟前
FastAPI + Redis Pub/Sub + WebSocket 组合解决方案的详细介绍
redis·websocket·fastapi
代码不行的搬运工28 分钟前
HTML快速入门-4:HTML <meta> 标签属性详解
java·前端·html
海盗强1 小时前
Babel、core-js、Loader之间的关系和作用全解析
开发语言·前端·javascript
猿榜编程1 小时前
python基础-requests结合AI实现自动化数据抓取
开发语言·python·自动化