跟华仔从0开始学架构-高性能缓存架构-笔记
缓存基本架构
缓存穿透:
缓存穿透指缓存没有发挥作用,业务系统虽然查缓存,但是缓存中没有数据,业务系统需要再次去存储系统查询数据。通常有以下原因导致:
1、存储数据不存在
被访问的数据真实不存在,则在缓存中不会存储相应的数据。通常情况,这种场景不会太多,一旦出现异常情况,如黑客攻击,故意大量访问读取不存在的数据业务,有可能将存储系统拖垮
2、缓存数据生成消耗大量时间和资源
这种情况是存储系统中存在数据,但生成缓存数据需要消耗大量的资源且耗时很长。如果刚好业务在访问的时候缓存失效了,那么缓存也没有发挥作用,压力落在了存储系统上
解决方案:
1、设置默认值;
2、通常情况下,读取页数据缓存足够用,需监控爬虫爬数据的情况;
缓存雪崩:
缓存失效后,引起系统性能的急剧下降。当缓存过期被清楚后,业务系统需要重新生成缓存,因此需要访问存储系统,再次进行运算。这个处理步骤耗时几十毫秒甚至上百毫秒。对于高并发的业务系统来说,几百毫秒内可能接到几百上千个请求。由于就的缓存已经被清楚,新的缓存还未生成,并且处理这些请求的线程都不知道其他请求正在生成缓存,所以都回去读取数据库,造成存储系统压力大。拖垮系统。
雪崩解决方案:
更新数据加锁机制和后台更新机制
1、更新锁
对于缓存更新操作进行加锁保护,保证只有一个线程可以进行更新缓存,未获取锁的线程要么等待锁释放后读取,要么返回空或者默认值,根据具体业务场景给定策略;
2、后台更新(实时更新+定时任务后台更新+人工触发更新)
不用业务线程来更新缓存,将缓存有效期设置为永久,后台线程定时更新缓存
后台定时任务更新缓存需要考虑一种场景::
当缓存系统内存不够用是,会“踢掉”一些缓存释放数据;如果业务系统读取到这些被踢掉的缓存,又不更新缓存,因此从业务系统看到的现象就是数据像丢失了一样,解决这种现象的方式有以下两种:
1、后台频繁查询缓存,发现数据丢失则更新缓存。读取时间间隔不能设置太长,且用户体验不好;
2、当业务系统发现数据丢失后,通过消息队列发送消息通知后台更新缓存;
后台更新数据需业务刚上新的时候进行缓存预热,缓存预热将缓存数据加载到缓存系统,而非等用户访问才出发加载缓存;
经典评论:
当面试的时候被问到数据库不是有缓存吗?为什么还用缓存系统
1、mysql第一种缓存叫sql语句结果缓存,条件苛刻,程序员不可控,一般线上都会关闭这个功能;
2、mysql的第二种缓存叫innodb buffer pool,缓存的是磁盘上的分页数据,不是sql查询结果,sql的执行过程升不了,而memcached和redis都是缓存sql的结果,两种缓存方式性能差很远;
好的缓存方案从以下几个方面入手设计:
1、什么数据应该被缓存
2、什么时候触发缓存以及触发缓存的方式是什么
3、缓存的层次和粒度
4、缓存的命名规则和失效规则
5、缓存的监控指标和故障应对方案
6、可视化缓存数据如redis具体key内容和大小
别人踩过的坑
1、将mysql md5做key查询结果存入缓存,结果业务系统数据不一致,要清楚缓存简直是噩梦,最后重启memcache;
2、缓存非银弹,既然允许数据缓存,那么在你是可以接受在一定时间区间内的数据不一致性的。(最终是一致的);
3、关键信息不缓存,如价格、库存等;
4、业务查询结果序列化后放redis,下次从redis取出来时保存,原来结果类虽然实现了serializble接口,但是没有重新serialVersionUID,导致不能返序列化;