文本紧接上文高并发系统-缓存(二)-如何使用缓存 设计一个通用的缓存组件
1. 原始需求
最近在做优惠券系统,其对并发要求比较高,大促期间领券峰值达到上万TPS,用券峰值也要到大几千TPS,其中峰值最高的是各种活动页、商详页中券信息漏出,可能会几万或者数十万QPS。
单单依靠数据库操作很难达到上述性能指标,其中相关数据分析如下:
- 优惠券批次信息属于配置信息,在领券、用券、查询券信息接口都会用到,调用量极高
- 优惠券领券数量、用券数量在领券/用券操作中就会变更,并发度较高
- 用户领取优惠券信息、优惠券状态等信息在优惠券中心、订单确认页选择优惠券时才会用到,并发度一般
2. 缓存设计思路
为了满足上述需求,设计本地缓存-REDIS缓存-数据库三级缓存。
- 本地缓存:为了缓存极度热度数据,并设置较低过期时间
- REDIS缓存:缓存配置数据、以及像优惠券领券数量之类频繁更新的不适合在数据操作数据
- 数据库:数据存储最终保证,上述本地缓存和REDIS缓存的数据源
通过CacheSDK实现上述缓存管理,一二三级缓存功能。
- 本地缓存采用Caffine来实现
- REDIS采用集群模式,采用REDISSION来与REDIS交互
- 三级缓存数据库(MYSQL)或者算法/接口执行结果
3. 关键设计点
3.1 如何保证数据一致性
采用Cache Aside(旁路缓存)的方式,参考前期文章高并发系统-缓存(二)-如何使用缓存
读策略(三级缓存):
- 从本地缓存中读取数据
- 如果本地缓存命中,则直接返回数据
- 如果本地缓存不命中,则从REDIS查询数据
- 如果REDIS缓存命中,会写本地缓存后返回
- 如果REDIS缓存未命中,则回调方法查询结果
- 会写REDIS和本地缓存并返回
写策略:
- 更新数据库中的记录
- 删除REDIS缓存记录,同时使用REDIS PUB/SUB模式,删除本地缓存
3.2 单个key获取流程
单个KEY 查询和新增如下:
3.3 批量key获取流程
批量KEY比较麻烦,主要涉及三级缓存汇聚过程,极端情况本地查询一部分,REDIS查询到一部分,MYSQL查询到一部分,最终要回写REDIS和本地缓存,最终返回。
具体实现见下篇。
参考
03 设计缓存架构时需要考量哪些因素?
经验分享 | 业务缓存之体系化设计与开发
系统设计常见组件 - Cache 篇
实现多级缓存架构设计方案