资料内容:
一、第一个缓存组件的开发
1、开发背景
2020 圣诞节前后业务流量受疫情恢复开始反弹,增值业务系统 db 的 qps 单库上涨至 3 万以上,核心
接口延迟增加,增值业务交易系统 load 节节升高,生单存在性能安全隐患。
经调查发现:
大量请求处在 IO 阻塞中且系统线程数(2000+)和活动线程过高,系统上下文切换开销大。
为此,我们团队做了很多性能优化的措施,其中最重要一个动作就是给数据库层加了一个特殊的缓存方
案,这个缓存方案就是我们开发的第一个缓存组件。
之前系统已有在用redis和guava缓存的,为什么这次还要再加一个针对 db 层的缓存方案呢?主要源于
以下几点:
本次性能问题突出在 db 上,db 的连接过高也在报警。
系统体量是很大的,仅交易系统有 30 万以上代码,系统内部流程和分支很多,直接在入口处做缓
存命中率不会很高,而系统最关键表结构只有 6 个,在此处做缓存更好收口。
这是个迭代过多年的系统,内部流程很长,上下文间经常有些对 db 重复的查询,改业务流程工作
量大需要回归的 case 太多。
交易系统对缓存的一致性要求极高,需要专用的缓存方案。除此之外,传统的与数据库有关的缓存方案在我们的业务场景 下是存在缺限的:
mysql 数据库端的查询缓存,这个缓存很鸡肋,只要数据发生变更相关缓存数据全部失效,对于
一个含订单交易的系统而言变更可是常态。
mybatis 二级存在,不仅一致性较差,其缓存粒度是基于 mapper , 一条数据的变更会将整个
mapper 的缓存数据清空。
使用 aop 和注解,基于方法直接在 dao 请求和 mysql 间加一个 redis ,这个如果没有更细节的设
计,分布式环境下的全局一致性是得不到保证的。
基于 binglog 同步做缓存,这个是有秒级内延迟的,不适用于交易系统。
2、设计思考
我们设计的这个缓存组件命名为 daoCache ,原于其加在 dao 层上,其主作用于分担数据库的 qps ,
以近 1:1 的比例将 mysql 的查询请求转移至 redis ,通过一套固化的流程和机制确保在分布式环境下
缓存数据与 db 具有较高一致性,同时尽可能对业务使用透明。
分布式场景的一致性理论基础 cap 原则和 base 理论告诉我们在分布式环境下无法在强一致性上去死
磕,分布式缓存完整的强制一致是一个不可解的问题, 工程实践时应主要考虑一致性、开发成本与性能
开销之间的平衡。由于这是一个重要的缓存方案,为了降低实践风险,我们做了充分的分析和思考。