前言
记录跟着做视频做项目,商品缓存处理的思维导图
思维导图
Redis
实战篇
短信验证码的登录注册功能
- 搭建项目
- 基于session的短信登录
- 集群下的session共享问题
- Redis实现共享session
- Redis实现session的刷新问题
商家查询缓存的功能
-
认识缓存
-
什么是缓存
- 一种具有高效读写能力的数据暂存区域
-
缓存的作用
- 降低后端负载
- 提高服务读写响应速度
-
缓存的成本
- 开发成本
- 运维成本
- 一致性问题
-
-
添加Reis缓存
-
缓存更新策略
-
三种策略
-
内存淘汰
- Redis自带的内存淘汰机制
-
过期淘汰
- 利用expire命令设置过期时间
-
主动更新
- 主动完成数据库与缓存的同时更新
-
-
策略选择
-
低一致性要求
- 内存淘汰和过期淘汰
-
高一致性要求
- 主动更新
- 过期淘汰兜底
-
-
主动更新的方案
-
Cache Aside
-
缓存调用者在更新数据库的同时完成对缓存的更新
- 一致性良好
- 实现难度一般
-
-
Read/Write Through
-
缓存与数据库集成为一个服务,服务保证两者的一致性,对外暴露API接口。调用者调用API,无需知道自己操作的是数据库还是缓存,不关心一致性。
- 一致性优秀
- 实现复杂
- 性能一般
-
-
Write Back
-
缓存调用者的CRUD都针对缓存完成。由独立线程异步的将缓存数据写到数据库,实现最终一致
- 一致性差
- 性能好
- 实现复杂
-
-
-
Cache Aside的模式选择
-
更新缓存还是删除缓存?
- 更新缓存会产生无效更新,并且存在较大的线程安全问题
- 删除缓存的本质是延迟更新,没有无效更新,线程安全问题相对较低
-
先操作数据库还是缓存?
-
先更新数据,再删除缓存
- 在满足原子性的情况下,安全问题概率较低
-
先删除缓存,再更新数据
- 安全问题概率较高
-
-
如何确保数据库与缓存操作的原子性
-
单体系统
- 利用事务机制
-
分布式系统
- 利用分布式事务机制
-
-
-
最佳方案
-
查询数据时
- 1、先查询缓存
- 2、如果命中,直接返回
- 3、如果缓存未命中,则查询数据库
- 4、将数据库数据写入缓存
- 5、返回结果
-
修改数据库时
- 1、先修改数据
- 2、然后删除缓存
- 确保两者的原子性
-
-
-
缓存穿透
-
产生原因
-
解决方案
-
缓存空对象
-
思路
- 不存在的数据Redis也在建立缓存,值为空,并设置一个较短的TTL时间
-
优点
- 实现简单,维护方便
-
缺点
- 额外的内存消耗
- 短期的数据不一致问题
-
-
布隆过滤
-
思路
- 利用布隆过滤算法,在请求进入Redis之前先判断是否是否存在
-
优点
- 内存占用少
-
缺点
- 实现复杂
- 存在误判的可能性
-
-
其他
- 做好数据的基础格式校验
- 加强用户权限校验
- 做好热点参数的限流
-
-
-
缓存雪崩
-
产生原因
- 在同一时间大量的缓存key同时失效或者Redis服务器宕机,导致大量的请求到达数据库,带来巨大的压力
-
解决方案
- 给不同的key添加随机值
- 利用Redis集群提高服务的可用性
- 给缓存业务添加降级限流策略
- 给业务添加多级缓存
-
-
缓存击穿(热点key)
-
产生原因
-
热点Key
- 在某一段时间被高并发访问
- 缓存重建耗时长
-
热点Key突然过期,因为重建耗时长,在这段时间内大量请求落到数据库,带来巨大冲击
-
-
解决方案
-
互斥锁
-
思路
- 在缓存重建过程加锁,确保重建过程只有一个线程执行,其他线程等待
-
优点
- 实现简单
- 没有额外内存消耗
- 一致性好
-
缺点
- 等待导致性能下降
- 有死锁风险
-
-
逻辑过期
-
思路
- 热点Key缓存永不过期,而是设置一个逻辑过期时间,查询数据时,通过对逻辑过期时间做出判断,来决定是否需要重建缓存
- 重建缓存也通过互斥锁保证单线程执行
- 重建缓存利用独立线程异步执行
- 其他线程无需等待,直接查询旧的数据即可
-
优点
- 线程无需等待,性能较好
-
缺点
- 不保证一致性
- 有额外内存消耗
- 实现复杂
-
-
-
-
缓存工具封装
- 这里用了泛型和函数式编程,以应对不同类型的数据
优惠卷
分布式锁
总结
感觉跟着整理一遍思维导图,感觉这几天的学习内容,思路清晰了一些。