| ||||||||||||||||||||||||||||||||||||
在电商系统缓存架构中,一致性方案的选择需结合业务场景特性(如数据重要性、实时性要求、并发量)、技术成本(开发复杂度、性能损耗)和风险容忍度(脏数据的影响范围)综合决策。以下是具体的选择框架和场景适配建议: 一、选择的核心维度 在决策前,需明确以下 3 个关键问题,以此划定方案的边界: 维度 核心考量 示例场景 数据重要性 脏数据是否会导致资损、用户投诉或业务中断? 高重要性:库存、支付金额、订单状态;低重要性:商品浏览量、用户昵称。 实时性要求 数据更新后,缓存需多久同步才算 “可接受”? 高实时性:秒杀库存(毫秒级);低实时性:商品分类(分钟级)。 读写比例 读多写少(优先优化读性能)还是写多读少(优先保障写一致性)? 读多写少:商品详情;写多读少:用户购物车(频繁添加 / 删除商品)。 二、按场景匹配方案 1. 核心高频场景:库存、订单、支付(强一致性倾向) 特性:数据错误直接导致资损(如超卖、价格错误),需接近强一致性,且并发量极高(如秒杀)。 适配方案: 基础策略:Cache Aside + 分布式锁 + 数据库事务 写操作:先通过数据库事务更新(如扣减库存),成功后删除缓存(避免缓存旧值),同时用分布式锁(如 Redis 的SETNX)防止并发写冲突。 读操作:缓存未命中时,加锁查询数据库并回填缓存,避免缓存击穿。 增强机制: 库存缓存只存 “预扣减后的值”,实际下单时再次校验数据库真实库存(兜底防超卖)。 引入消息队列异步重试(如删除缓存失败时,通过 MQ 重试确保缓存最终被删除)。 示例:秒杀场景中,商品库存更新流程: 用分布式锁锁定商品 ID,确保同一时间只有一个线程操作。 数据库事务内扣减库存(UPDATE stock SET num=num-1 WHERE id=? AND num>0)。 事务提交后,删除缓存中该商品的库存值。 释放锁,其他线程读取时因缓存未命中,会重新查询数据库并更新缓存。 2. 非核心实时场景:商品详情、用户地址(最终一致性) 特性:允许短时间不一致(如商品描述更新后,缓存延迟 1 秒同步),但需最终正确,读并发量高、写操作少。 适配方案: 基础策略:Cache Aside + 定期全量同步 写操作:更新数据库后删除缓存(避免直接更新缓存导致的并发覆盖问题)。 读操作:缓存未命中时查库回填,命中则直接返回(容忍毫秒级延迟)。 增强机制: 为缓存设置合理过期时间(如 30 分钟),即使删除缓存失败,也会自动过期并刷新。 每日凌晨执行全量同步任务(从数据库批量刷新缓存),修正可能的长期不一致。 示例:商品详情页更新(如修改商品描述): 运营修改数据库中的商品描述字段。 调用接口删除缓存中该商品的详情 Key。 下次用户访问时,缓存未命中,查询数据库后写入新值(旧用户可能看到 1 秒内的旧描述,不影响核心体验)。 3. 写密集场景:购物车、用户积分(平衡性能与一致性) 特性:写操作频繁(如用户频繁添加 / 删除购物车商品),读操作也高频,但允许短暂不一致(如购物车商品数量延迟 1 秒同步)。 适配方案: 基础策略:Write Back(写回模式)+ 版本号控制 写操作:只更新缓存(如购物车 Redis 哈希结构),缓存异步批量更新数据库(如每 5 秒或缓存条目数达 100 时批量写入)。 读操作:直接读缓存(性能优先),通过版本号避免旧值覆盖(如每次更新时版本号 + 1,写入数据库时只保留最新版本)。 风险控制: 缓存集群开启持久化(如 Redis 的 AOF+RDB),防止宕机丢失数据。 对核心字段(如购物车商品 ID),同步更新数据库(避免关键数据丢失)。 示例:用户连续 3 次修改购物车商品数量: 第 1 次修改:缓存数量 = 2,版本号 = 1(异步待写入数据库)。 第 2 次修改:缓存数量 = 3,版本号 = 2(覆盖前一次异步任务)。 第 3 次修改:缓存数量 = 1,版本号 = 3(最终异步写入数据库,只保留版本号 = 3 的数据)。 4. 低重要性场景:商品浏览量、评价数(最终一致性 + 简化方案) 特性:数据错误影响极小(如浏览量少算 1 次),读写频率高,但无需复杂保障。 适配方案: 基础策略:Cache First(缓存优先)+ 定时刷新 写操作:直接更新缓存(如浏览量 + 1),不立即同步数据库。 读操作:只读缓存(完全依赖缓存数据)。 定时任务:每小时将缓存中的计数批量同步到数据库(允许 1 小时内的不一致)。 优势:开发简单,性能极高(无需操作数据库)。 示例:商品详情页 “浏览量” 统计: 用户访问时,缓存中view_count:123直接 + 1(无需查库)。 每小时执行任务:SELECT sum(view_count) FROM cache → 写入数据库并重置缓存计数。 三、避坑原则:避免过度设计或方案错配 不盲目追求 “强一致性”: 强一致性方案(如写透模式、分布式锁)会牺牲性能,非核心数据使用会导致系统瓶颈(如商品评价无需分布式锁)。 容忍 “可控的不一致”: 明确 “不一致的最大时长”(如商品价格允许 5 秒延迟),在此范围内用最终一致性方案降低成本。 兜底机制必须存在: 无论选择哪种方案,需有监控(如缓存与数据库数据差异告警)和补偿机制(如定时全量同步),防止异常场景下的长期脏数据。 总之,电商缓存一致性方案的选择,本质是 “业务价值与技术成本的平衡”: 核心数据(库存、订单):用Cache Aside + 分布式锁 + 事务保障强一致性倾向,容忍轻微性能损耗。 非核心数据(商品详情):用Cache Aside + 定期同步实现最终一致性,优先保证性能。 写密集 / 低重要数据:用写回模式或缓存优先简化方案,降低开发复杂度。 最终需通过压测和灰度发布验证方案的适配性,避免 “纸上谈兵”。 | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||||||||
|