缓存受益/ 成本/ 更新策略 / 穿透/ 无底洞/
1.缓存的受益与成本
受益:
1)加速读写
2)降低后端负载
后端服务器通过前端缓存降低负载,业务端使用Redis降低后端MySQL负载
成本
1)数据不一致:缓冲层和数据层有时间窗口不一致,和更新策略有关。
2)代码维护成本:多了一层缓存逻辑
3)运维成本:如Redis Cluster
2.缓存使用场景
1)降低后端负载
对高消耗的SQL:join结果集/分组统计结果缓存(如截至某段时间的缓存)
2)加速请求响应
利用Redis/Memcache优化IO响应时间
3)大量写合并为批量写:
某个操作如计算访问量,如果直接和DB连接,会造成大量更新操作,DB写的速度慢,造成性能差。则计数器先Redisl累加再批量写DB。
3.缓存更新策略
缓存的数据拥有生命周期,需要定期更新或删除,从而保证空间在可控范围内,并且保证数据的更新。
更新策略:
1)LRU / LFU / FIFO算法剔除:例如maxmemory-policy
适用场景:最大内存
2)超时提出:例如expire
3)主动更新:开发控制每个key的生命周期。例如,在存储层用户的信息发生变化,如果通过一定的业务代码或是开发工具,能订阅存储层的更新,来更新缓存层中的数据,来实现数据的一致性。
更新建议:
1)低一致性:最大内存和淘汰策略
2)高一致性:超时剔除和主动更新结合,最大内存和淘汰测率兜底。(建议)
4.缓存力度控制
缓存三个角度
1)通用性:全量属性更好
2)占用空间:部分属性更好
3)代码维护:表面上全量属性更好
一般都缓存一部分属性,虽然缓存全量属性系统有利于后续的扩展,但是序列化和内存上开销较大,而且有些功能成功后不怎么会再进行大的扩展。
5.缓存穿透问题
1)业务代码自身问题
2)恶意攻击、爬虫等
视频网站:视频的URL进过加密,防止恶意人员猜测视频id规格,强制访问,然后造成穿透问题
如何发现缓存穿透
1)业务的响应时间
利用监控系统监控,请求都打到存储层,则会对响应时间造成影响(缓存会比直接查存储层快),因此可以通过监控来发现。
2)业务本身的问题
3)相关指标:总调用数,缓存层命中数,存储层命中数
解决缓存击穿:
方法一:缓存空对象
缺点:1)需要更多的键:恶意攻击或爬虫有许多的键,虽然只存储键和null,但是数量很大时,从缓存的使用上来说会有一定的影响。
2)缓存层和存储层数据"短期"不一致:例如调用存储层接口时网络不通,导致拿不到对应的结果(过期时间设为5分钟),其实存储层是有这个数据的,但是由于网络原因导致了数据在缓存过期时间内是不一致的。【可以在接口恢复正常时刷新缓存中的数据】
方法二:布隆过滤器
布隆过滤器在cache层之前进行过滤,如果布隆过滤器中被过滤,则认为这个请求是无效的,反之,认为它是有效的。【固定的数据布隆过滤器效果好,但是如果变化的数据,如果构建布隆过滤器】
6.无底洞问题优化
无底洞问题主要考虑通信开销,方法有串行mget,串行IO,并行IO,hash_tag
8.热点key重建优化
有大量的线程都会做缓存重建,查询数据源,这样导致数据源有很大的压力,而且响应时间会变得很慢。
三个目标
1)减少重缓存的次数
2)数据尽可能一致
3)减少潜在危险
两个解决
1)互斥锁
互斥锁的方法解决了大量重建的问题,但是它会有大量线程在等待的问题。
2)永不过期
a.缓存层面:没有设置过期时间(无expire)
b.功能层面:为每个value添加逻辑过期时间,但发现超过逻辑过期后,会使用单独的线程取构建缓存。相比于互斥锁的方案,此方案没有等待的过程,但会存在数据不一致,因为没有等到真正缓存重建完,可能拿到老的结果。