一、缓存雪崩:
1、缓存失效时间相同导致大量缓存同时失效
- 缓存时间加随机因子,不同商品设置不同失效时间
2、缓存系统故障
- 事前:增加缓存系统高可用方案设计,避免出现系统性故障(主从、集群)
- 事故中:
- 增加多级缓存,在单一缓存故障时,仍有其他缓存系统可用,如内存级缓存->Redis这样的方案;
- 启用
熔断限流机制
,只允许可承受流量,避免全部流量压垮系统(hystrix)
- 事后:缓存数据持久化,在故障后快速恢复缓存系统
二、缓存穿透
1、访问不存在数据从而绕过缓存,直接读取数据库
- 数据不存在时,在缓存系统设置空值
- 布隆过滤器bloomfilter
三、缓存一致性
1、常规流程是:读操作:命中缓存则返回,无缓存则读数据库并写缓存;写操作:先删除缓存,再更新数据库。会出现的问题是当写操作先删除缓存尚未更新数据库时,读操作未命中缓存所以读数据库并写缓存,然后写操作更新数据库,导致缓存中数据和数据库不一致
- bug版 - 加事务解决更新缓存失败问题:在事务中处理,先更新数据库再删除缓存,同时成功后才提交事务。这种方式还是保证不了一致性,当更新数据并删除缓存后事务准备提交时,有别的请求过来查询旧数据到缓存中仍然造成不一致。
- 升级bug版 - 加事务并在事务结束后再次删缓存:那第二次删除缓存失败了咋整?此法还是不行
- 最终一致性方案:事实上很多大公司的代码规范中都规定不要在事务中调用远程服务,因为在处理速度上来说,cpu > 操作系统缓存 > 内存 > 磁盘 > 网络,网络调用会花费大量时间,大事务会造成数据库吞吐量降低,因此摒弃事务这种方法。既然保证不了强一致性,就保证最终一致性:先更新数据库,成功后再删除缓存,若删除失败则将失败消息发送到MQ,MQ不断重试让缓存失效,使用MQ来保证缓存和数据库的最终一致性。实际上这种方法还是有问题,当删除缓存失败了要向MQ发消息时,服务器宕机或重启了导致消息没有发送到MQ,怎么办?具体更深入的研究请参考以下链接。
参考:http://fivezh.github.io/2019/02/11/cache-things/?utm_source=tuicool&utm_medium=referral
https://blog.youkuaiyun.com/liubenlong007/article/details/79744417