Appearance
购物车服务里的缓存和价格刷新怎么设计
先说结论
- 购物车适合缓存化,但价格不能只信缓存展示值,结算前必须重新校验
- 购物车里存“购买意图”和必要快照,不要把商品完整详情全部塞进去
- 商品变价、失效、库存波动要通过异步刷新和结算前兜底一起处理
一、购物车里到底该存什么
更推荐存这些字段:
- 用户 ID
- SKU ID
- 数量
- 勾选状态
- 加购时的展示价
- 商品标题、图片等少量展示快照
- 更新时间
不建议直接塞进去的:
- 完整商品详情
- 实时库存余量
- 实时营销规则明细
- 大量冗余属性 JSON
原因很简单:购物车读多写也不少,一旦对象过大,网络和缓存成本都会明显上来。
二、价格为什么不能只信购物车缓存
购物车页看到的价格,本质上只是“展示价格”。
真正下单时必须重新计算:
- 当前 SKU 售价
- 活动价是否生效
- 优惠券是否可用
- 用户等级价是否变化
- 库存是否足够
所以更稳的链路通常是:
- 购物车负责快速读写和展示。
- 结算页重新拉一次商品、库存、营销信息。
- 下单前再做最终价格确认。
三、缓存结构怎么选更方便
常见做法是按用户维度存:
cart:{userId}-> hash 或 JSON- 每个 field 对应一个 SKU
- 同步保存最近更新时间和勾选状态
这种结构的好处是:
- 读一个用户购物车比较自然
- 登录合并和失效清理更方便
- 可以按用户做限长和过期治理
如果还要支持游客购物车,常见做法是:
- 游客态放本地或短期 Redis key
- 登录后做合并
- 合并时按 SKU 去重,并保留较新的数量与勾选状态
四、商品变价和失效怎么处理
1. 轻量异步刷新
商品改价、下架、库存规则变化后,通过消息或定时任务把受影响购物车标记成“待刷新”。
2. 页面展示明确提示
如果某个商品价格已变、库存不足、活动失效,应该在购物车页直接标明,而不是等到提交订单才报错。
3. 下单前最终校验
这是最后一道兜底。即便缓存没及时刷新,也不能让错误价格直接进入订单。
五、最容易踩的坑
1. 购物车价格当成下单最终价格
只要活动、库存或会员价发生变化,就会出现价格不一致争议。
2. 购物车对象做得太大
前期看不出问题,后面一旦用户购物车商品多、字段多,Redis 内存和网络开销都会放大。
3. 登录合并逻辑写得太随意
游客态和登录态一合并,数量、勾选状态、优惠信息容易打架。
4. 缓存失效只靠 TTL
TTL 只能做兜底,商品变更、价格变更、营销失效更适合走主动刷新。
总结
购物车服务的关键,不是把所有商品信息都缓存起来,而是把“购买意图、展示快照、结算重算”这三层边界分开。购物车负责快,结算负责准,下单负责兜底,这样整条链路会稳很多。