缓存策略
-
redis内部自动更新—>低一致性
-
设置TTL定时更新—>一致性一般,更新频率高
-
主动更新—>主动更新
-
三大策略之一“Cache Aside”
-
考虑1:更新缓存还是删除缓存?——删除缓存
- 原因:更新缓存可能造成读少写多,浪费性能
-
考虑2:先删除缓存再更新数据库?or先更新数据库后删除缓存?——后者
- 原因:前者安全问题产生概率大,后者在满足原子性(一定执行完成)的情况下,安全问题发生概率低。
- 怎么保证原子性:
- 单体系统:事务机制(@Transactional)
- 分布式系统:分布式事务机制
-
-
缓存穿透
- 产生原因:客户端的请求数据在缓存和数据库中都不存在,这样导致每次请求都跳过缓存,使缓存永久失效,请求直接打在数据库上。
- 解决方案:
- 缓存空对象
- 对于不存在的数据同样产生缓存,值为空“”,并设置一个较短的TTL。
- 优点:简单易实现,维护方便
- 缺点:消耗额外内存,短期的数据不一致性
- 对于不存在的数据同样产生缓存,值为空“”,并设置一个较短的TTL。
- 布隆过滤
- 利用布隆过滤算法,在请求进入redis前先判断请求是否存在,如果不存在直接返回。
- 优点:内存占用少
- 缺点:实现复杂,可能产生误判
- 利用布隆过滤算法,在请求进入redis前先判断请求是否存在,如果不存在直接返回。
- 其他:
- 做好数据的基础格式校验(为需要传递的值设置特定格式并判断)
- 加强用户权限控制(不让随便什么用户都可以请求一些重要的页面)
- 做好热点参数限流(防止请求过多?)
- 缓存空对象
缓存雪崩
- 产生原因:在同一时间大量的缓存key失效或者redis服务宕机,导致大量的请求到达数据库,给数据库带来巨大压力,如同雪崩。
- 解决方案:
- 给不同的key的TTL添加随机值(避免同时失效)
- 利用redis集群提高服务的可用性(避免一台宕机全部挂掉)
- 给缓存业务添加降级限流策略(实现请求的快速返回,不让请求到达数据库)
- 添加多级缓存*
缓存击穿
-
产生原因:热点key突然失效,并且缓存重建耗时较长,在这期间有大量的请求落到数据库上,给数据库带来巨大压力。
热点key:在某一时段高并发,缓存重建时间长。
-
解决方案:
- 互斥锁:给数据重建过程添加锁,确保重建过程只能一个线程操作。
- 优点:实现简单,没有额外内存消耗,一致性好
- 缺点:重建过程其他没有获得锁的线程会重试获取锁,加大性能消耗,还可能有死锁的情况发生
- 逻辑过期:热点key缓存永不过期,而是设置一个逻辑过期时间,查询到的数据通过逻辑过期时间来决定是否需要重建缓存;重建的过程也需要互斥锁来保证单线程重建,重建过程由一条新的线程来异步进行,旧线程与其他未获得锁的线程则直接返回旧的缓存数据。
- 优点:线程无需等待,性能较好
- 缺点:不保证一致性、有额外的内存消耗、实现复杂
- 互斥锁:给数据重建过程添加锁,确保重建过程只能一个线程操作。