缓存设计
- 收益
- 加速读写
- 降低后端MySQL等数据库的负载
- 成本
- 缓存层和数据层由于更新策略,导致数据不一致
- 编码增加一层缓存层的逻辑代码
- 以及运维成本
- 使用场景
- 对高消耗的分组查询和多表查询结果进行缓存
- 加速请求响应时间
- 大量写合并成批量写,比如计数器,先将计数暂存缓存中,过一段时间再存入MySQL,减少对MySQL的访问
缓存更新策略
-
仅使用Redis内置的内存回收策略
-
超时剔除:手动为key设置过期时间,即
expire
属性 -
主动更新:定时更新(每隔一段时间想数据源询问数据是否变化)、监控数据源的变化(发布更新消息,缓存层订阅,收到更新消息后更新缓存)
缓存粒度
- 存储全部属性更占空间,但是通用性高,代码维护成本低
- 存储部分属性占用空间少,但是通用性低,代码维护成本高
缓存穿透
缓存雪崩
请求流量直接压向底层数据源,数据源无法承受访问压力
- 缓存倾斜(宕机):缓存服务器无法承受访问压力,缓存服务器宕机,导致流量转向底层数据源
- 解决方案:保证缓存服务器的高可用性,甚至做二级缓存
- 缓存同时失效:设置了很多相同的过期时间的key,导致缓存在某一时刻同时失效,导致流量转向底层数据源
- 解决方案:将过期时间设置为一个随机时间
- 缓存击穿:热点key突然失效,并且缓存重建时间较长,有大量的线程会去查询数据源并重建缓存,导致流量转向底层数据源
- 解决方案:使用互斥锁(分布式锁),只有第一个线程进行缓存重建,其他线性阻塞等待
缓存污染
由于程序的错误处理(比如异常处理不当),导致向缓存中存储了错误的处理结果,下次再从缓存中取时任然是错误的结果
解决方案:正确的异常处理,当计算结果出错或发生异常时,将错误的计算结果或异常信息从缓存中删除
缓存无底洞
集群中添加机器时,客户端的性能不但没提升,反而下降
更多的机器等于数据增长与水平扩展,并不意味着更高的性能,因为集群多个节点之间通信也需要消耗资源
优化方案:命令本身优化、减少网络通信次数、降低连接成本(使用长连接/连接池、NIO等)
Comments NOTHING