♨️本篇文章记录的为Redis知识中
缓存穿透,缓存击穿,缓存雪崩,缓存预热
中秒杀相关内容,适合在学Java的小白,帮助新手快速上手,也适合复习中,面试中的大佬🙉🙉🙉。
♨️如果文章有什么需要改进的地方还请大佬不吝赐教❤️🧡💛
前言:
参考了redis的相关学习课程,并总结了一些redis实战过程中的高频面试题,模拟了一些实际业务场景
@[TOC]
文章目录:
🎠 缓存更新策略
数据库和缓存不一致采用什么方案
综合考虑使用方案一,但是方案一调用者如何处理呢?这里有几个问题
操作缓存和数据库时有三个问题需要考虑:
如果采用第一个方案,那么假设我们每次操作数据库后,都操作缓存,但是中间如果没有人查询,那么这个更新动作实际上只有最后一次生效,中间的更新动作意义并不大,我们可以把缓存删除,等待再次查询时,将缓存中的数据加载出来
删除缓存还是更新缓存?
- 更新缓存:每次更新数据库都更新缓存,无效写操作较多
- 删除缓存:更新数据库时让缓存失效,查询时再更新缓存
如何保证缓存与数据库的操作的同时成功或失败?
- 单体系统,将缓存与数据库操作放在一个事务
- 分布式系统,利用 TCC 等分布式事务方案
应该具体操作缓存还是操作数据库,我们应当是先操作数据库,再删除缓存,原因在于,如果你选择第一种方案,在两个线程并发来访问时,假设线程 1 先来,他先把缓存删了,此时线程 2 过来,他查询缓存数据并不存在,此时他写入缓存,当他写入缓存后,线程 1 再执行更新动作时,实际上写入的就是旧的数据,新的数据被旧数据覆盖了。
先操作缓存还是先操作数据库?
- 先删除缓存,再操作数据库
- 先操作数据库,再删除缓存
🔥缓存预热
场景:“宕机” 服务器启动后迅速宕机
🔥问题排查:
1.请求数量较高,大量的请求过来之后都需要去从缓存中获取数据,
但是缓存中又没有,此时从数据库中查找数据然后将数据再存入缓存,
造成了短期内对redis的高强度操作从而导致问题
2.主从之间数据吞吐量较大,数据同步操作频度较高
🔥解决方案:
前置准备工作:
1.日常例行统计数据访问记录,统计访问频度较高的热点数据
2.利用LRU数据删除策略,构建数据留存队列例如:storm与kafka配合
准备工作:
1.将统计结果中的数据分类,根据级别,redis优先加载级别较高的热点数据
2.利用分布式多服务器同时进行数据读取,提速数据加载过程
3.热点数据主从同时预热
实施:
4.使用脚本程序固定触发数据预热过程
5.如果条件允许,使用了CDN(内容分发网络),效果会更好
🔥总的来说:
缓存预热就是系统启动前,提前将相关的缓存数据直接加载到缓存系统。避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓存数据!
🎠 缓存穿透
缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,不断发起这样的请求,这些请求都会打到数据库,给数据库带来巨大压力。
🥝常见的解决方案有两种:
- ♨缓存空对象
- 优点:
- 实现简单,维护方便
- 缺点:
- 额外的内存消耗
- 可能造成短期的不一致
- 优点:
- ♨布隆过滤
- 优点:
- 内存占用较少,没有多余 key
- 缺点:
- 实现复杂
- 存在误判可能
- 优点:
🥝面试场景hr:数据库服务器又崩溃了,跟之前的一样吗?
1.系统平稳运行过程中
2.应用服务器流量随时间增量较大
3.Redis服务器命中率随时间逐步降低
4.Redis内存平稳,内存无压力
5.Redis服务器CPU占用激增
6.数据库服务器压力激增
7.数据库崩溃
🥝问题排查:
1.Redis中大面积出现未命中
2.出现非正常URL访问
🥝问题分析:
1. 获取的数据在数据库中也不存在,数据库查询未得到对应数据
2.Redis获取到null数据未进行持久化,直接返回
3.下次此类数据到达重复上述过程
4.出现黑客攻击服务器
🥝解决方案:
1.缓存null值
2.布隆过滤
3.增强id的复杂度,避免被猜测id规律
4.做好数据的基础格式校验
5.加强用户权限校验
6.做好热点参数的限流
❄️缓存雪崩
缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机,导致大量请求到达数据库,带来巨大压力
❄️场景:数据库服务器崩溃,一连串的场景会随之儿来
1.系统平稳运行过程中,忽然数据库连接量激增
2.应用服务器无法及时处理请求
3.大量408,500错误页面出现
4.客户反复刷新页面获取数据
5.数据库崩溃
6.应用服务器崩溃
7.重启应用服务器无效
8.Redis服务器崩溃
9.Redis集群崩溃
10.重启数据库后再次被瞬间流量放倒
❄️问题排查:
1.在一个较短的时间内,缓存中较多的key集中过期
2.此周期内请求访问过期的数据,redis未命中,redis向数据库获取数据
3.数据库同时接收到大量的请求无法及时处理
4.Redis大量请求被积压,开始出现超时现象
5.数据库流量激增,数据库崩溃
6.重启后仍然面对缓存中无数据可用
7.Redis服务器资源被严重占用,Redis服务器崩溃
8.Redis集群呈现崩塌,集群瓦解
9.应用服务器无法及时得到数据响应请求,来自客户端的请求数量越来越多,应用服务器崩溃
10.应用服务器,redis,数据库全部重启,效果不理想
总而言之就两点:短时间范围内,大量key集中过期
❄️解决方案:
1.给不同的Key的TTL添加随机值
2.利用Redis集群提高服务的可用性
3.给缓存业务添加降级限流策略
(短时间范围内牺牲一些客户体验,限制一部分请求访问,
降低应用服务器压力,待业务低速运转后再逐步放开访问)
4.给业务添加多级缓存(Nginx缓存+redis缓存+ehcache缓存)
5.检测Mysql严重耗时业务进行优化
(对数据库的瓶颈排查:例如超时查询、耗时较高事务等)
❄️落地实践:
1.LRU与LFU切换
2.数据有效期策略调整:
根据业务数据有效期进行分类错峰,A类90分钟,B类80分钟,C类70分钟
过期时间使用固定时间+随机值的形式,稀释集中到期的key的数量
3.超热数据使用永久key
4.定期维护(自动+人工)
对即将过期数据做访问量分析,确认是否延时,配合访问量统计,做热点数据的延时
5.加锁:慎用!
❄️总的来说:
缓存雪崩就是瞬间过期数据量太大,导致对数据库服务器造成压力。如能够有效避免过期时间集中,可以有效解决雪崩现象的出现(约40%),配合其他策略一起使用,并监控服务器的运行数据,根据运行记录做快速调整。
⚡缓存击穿
缓存击穿问题也叫热点Key问题,就是一个被高并发访问并且缓存重建业务较复杂的key突然失效了,无数的请求访问会在瞬间给数据库带来巨大的冲击。
⚡场景:还是数据库服务器崩溃,但是跟之前的场景有点不太一样
1.系统平稳运行过程中 2.数据库连接量瞬间激增 3.Redis服务器无大量key过期 4.Redis内存平稳,无波动 5.Redis服务器CPU正常 6.数据库崩溃
⚡问题排查:
1.Redis中某个key过期,该key访问量巨大
2.多个数据请求从服务器直接压到Redis后,均未命中
3.Redis在短时间内发起了大量对数据库中同一数据的访问
总而言之就两点:单个key高热数据,key过期
⚡解决方案:
1.预先设定
以电商为例,每个商家根据店铺等级,指定若干款主打商品,在购物节期间,
加大此类信息key的过期时长 注意:购物节不仅仅指当天,以及后续若干天,
访问峰值呈现逐渐降低的趋势
2.现场调整
监控访问量,对自然流量激增的数据延长过期时间或设置为永久性key
3.后台刷新数据
启动定时任务,高峰期来临之前,刷新数据有效期,确保不丢失
4.二级缓存
设置不同的失效时间,保障不会被同时淘汰就行
5.加锁&逻辑过期 (重点)
分布式锁,防止被击穿,但是要注意也是性能瓶颈,慎重!
♟️互斥锁
- 优点
- 没有额外的内存消耗
- 保证一致性
- 实现简单
- 缺点
- 线程需要等待,性能受影响
- 可能有死锁风险
- 优点
♟️逻辑过期
- 优点
- 线程无需等待,性能较好
- 缺点
- 不保证一致性
- 有额外内存消耗
- 实现复杂
- 线程无需等待,性能较好
- 优点
⚡总的来说:
缓存击穿就是单个高热数据过期的瞬间,数据访问量较大,未命中redis后,发起了大量对同一数据的数据库访问,导致对数 据库服务器造成压力。应对策略应该在业务数据分析与预防方面进行,配合运行监控测试与即时调整策略,毕竟单个key的过期监控难度较高,配合雪崩处理策略即可。
如果这篇【文章】有帮助到你💖,希望可以给我点个赞👍,创作不易,如果有对Java后端或者对redis感兴趣的朋友,请多多关注💖💖💖
👨🔧个人主页:阿千弟
如果大家对redis相关知识感兴趣请点击这里👉👉👉redis专栏学习