电商购物车怎么设计?一次讲清存储模型、价格刷新、勾选状态与并发更新思路

大家好,我是一名有 4 年工作经验的 Java 后端开发。
购物车看起来像电商系统里最普通的模块,但真正做过的人都知道,它其实连接着商品、库存、价格、优惠、下单、登录态同步等很多环节。
这篇文章我想系统聊一聊购物车到底应该怎么设计。

🦅个人主页
🐼


一、购物车为什么没那么简单

很多人会觉得购物车很简单:

  • 用户加个商品
  • 选个数量
  • 提交订单时一起带过去

但真实系统里,购物车至少会碰到这些问题:

  • 未登录购物车和登录购物车怎么合并
  • 商品下架后购物车怎么展示
  • 价格变了以后购物车要不要实时刷新
  • 勾选状态放哪里
  • 数量更新是走 Redis 还是数据库
  • 下单时购物车快照怎么和真实商品校验联动

也就是说,购物车真正难的不是“存个列表”,而是:

如何在体验、实时性、一致性和成本之间取平衡。


二、购物车里到底要存什么

我更建议购物车里只存:

  • 用户 ID
  • SKU ID
  • 数量
  • 勾选状态
  • 加入时间

而这些内容通常不建议长期冗余存:

  • 商品名称
  • 图片
  • 实时价格
  • 库存

因为这些更适合在查询购物车时实时补齐。

为什么?

因为:

  • 商品名称会改
  • 图片会改
  • 价格会改
  • 活动价会变
  • 库存会变

所以购物车更像“意向清单”,不是订单快照。


三、数据库和 Redis 怎么选

3.1 Redis 适合什么

适合:

  • 高频读写
  • 未登录购物车
  • 用户临时态
  • 快速加购 / 改数量

3.2 MySQL 适合什么

适合:

  • 登录用户购物车
  • 持久化存储
  • 跨端同步
  • 长期保存

3.3 最常见的落地方式

我更建议:

未登录购物车放 Redis / Cookie,登录购物车最终落 MySQL,热点读可配 Redis 缓存。

如果系统体量不大,也可以:

直接 MySQL 持久化 + Redis 做热点加速


四、推荐表结构

CREATE TABLE cart_item (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    user_id BIGINT NOT NULL,
    sku_id BIGINT NOT NULL,
    quantity INT NOT NULL,
    selected TINYINT NOT NULL DEFAULT 1,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    UNIQUE KEY uk_user_sku (user_id, sku_id)
);

这个表设计的重点:

  • 一个用户一个 SKU 只保留一条
  • 重复加购时直接改数量

五、核心流程怎么设计

5.1 加入购物车

逻辑通常是:

  • 如果购物车里没有该 SKU,就插入
  • 如果有,就累加数量

5.2 修改数量

逻辑通常是:

  • 校验购买上限
  • 校验是否已下架
  • 更新数量

5.3 勾选 / 取消勾选

逻辑通常是:

  • 更新 selected

5.4 查询购物车

查询时通常要补齐:

  • 商品标题
  • 图片
  • 当前售价
  • 是否下架
  • 是否缺货

也就是说:

购物车展示数据通常是“购物车明细 + 商品快照实时补齐”的组合结果。

5.5 提交订单

提交订单时,不能只相信购物车里原来的信息,而必须重新校验:

  • 商品是否可售
  • 数量是否足够
  • 当前价格是否变化

六、最容易踩的坑

6.1 把实时价格直接长期存购物车

价格一变,购物车就会和商品真实价格不一致。

6.2 不做唯一键,导致同一个 SKU 多条记录

后面合并和计算会很麻烦。

6.3 提交订单时直接信购物车价格

这是非常危险的,必须重新校验商品最新价格和库存。

6.4 未登录购物车和登录购物车合并没设计好

用户登录后很容易出现:

  • 数量冲突
  • 重复商品
  • 勾选状态丢失

七、面试中怎么回答

如果面试官问你:

电商购物车一般怎么设计?

你可以这样回答:

第一,购物车本质上更像用户的购买意向清单,所以我通常只在购物车里存用户、SKU、数量、勾选状态这些稳定字段,而不会把价格、库存等强实时字段长期固化在购物车表里。

第二,登录用户购物车我一般会落 MySQL 做持久化,未登录购物车可以先放 Redis 或前端本地,登录后再做合并。

第三,购物车查询时会实时补齐商品标题、图片、价格、库存状态等信息,提交订单时再重新做一次商品可售、价格和库存校验,而不会直接信任购物车中的历史数据。

第四,为了防止一个用户对同一个 SKU 出现多条记录,购物车表通常会对 user_id + sku_id 做唯一约束。


八、总结

购物车系统真正难的不是表结构,而是如何平衡:

  • 用户体验
  • 实时价格
  • 库存一致性
  • 跨端同步
  • 持久化成本

如果只记一句结论,我觉得可以记住这句:

购物车更适合存“用户想买什么”,而不是长期保存“商品现在是什么样”,下单时一定要重新校验商品真实状态。


九、结尾

如果你觉得这篇文章对你有帮助,欢迎点赞、收藏、关注。
后面我会继续整理一些更偏实战的 Java 后端和电商系统设计文章。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐