今天分享下项目中使用缓存对项目进行性能优化
背景
- 项目中流量高峰时,db的qps达到15k左右,线程数达到5k(服务器设置的最大连接数),创建链接最高耗费达到2s。数据库服务器的连接数以及cpu升高,处理能力下降,响应时间变长
- 接口提供的批量接口查询很多资源,设计到大量班期时存在性能问题
原因分析
- 库存服务没有针对请求区分核心流程和非核心流程,所有读写操作都是直接操作写库
- 当非核心(可降级)的查询量大时,直接影响了核心应用的可用性,间接影响到了订单环节的扣还库存等相关操作
- 接口内缓存使用不充分
优化方案
- 核心与非核心隔离
- 核心应用: 特点:数据实时性要求高,请求量小,对服务稳定性要求高,影响预订和订单;单独部署
- 非核心应用:特点:数据实时性要求相对较低,请求量大,对服务稳定性相对较低,不影响预订和下单,可降级处理
- 对于非核心应用的调用,当服务的可用性降低,比如redis故障请求击穿缓存都命中db,对db造成压力的情 况下,避免影响核心应用,使用开关控制,切换成无限库存模式
- 针对非核心的查询使用从库
- 主从分离
- 接口使用多级缓存优化查询性能
- 数据更新需要主动更新缓存以保证缓存的数据实时性
- 对于未更新的数据,使用被动更新缓存,提高缓存命中率
- 适当提高缓存时间
- 对于查无结果的数据,使用特殊对象填充缓存,提高缓存命中率,防止缓存击穿
- 监听mysql canal消息主动刷新缓存
- 添加短时间内的本地缓存,行程二级缓存
优化效果
- API响应性能提升40%
- 缓存命中率97%以上
- 非核心查询的数据与写库延迟2s内,系统各项指标更平稳
经验总结
- 结合使用场景和数据特点进行设计
- Key的设计 考虑加版本号
- 慎用跨应用缓存
- 慎用长时间的缓存
- 尽量不要缓存大对象
- 超短时间的本地缓存
- 留条后路 开关和刷缓存接