当前位置: 首页 > news >正文

系统设计实战 19:设计购物车系统(Shopping Cart)

🚀 系统设计实战 19:设计购物车系统(Shopping Cart)

摘要:购物车是电商系统的流量入口,涉及离线/在线购物车合并、多端同步、高并发读写、价格计算等核心问题。本文深入剖析 Redis Hash 存储方案、离线合并策略、购物车结算优化,并提供完整的 Java 实现。


🎯 场景引入

你往购物车加了 3 件商品,关掉 App 第二天打开还在。换到电脑端,购物车也同步了。

核心挑战

  1. 多端同步:手机、电脑、iPad 上的购物车如何实时一致?
  2. 库存联动:购物车里的商品下架了、涨价了,怎么处理?
  3. 高并发:双十一前夜,上亿用户疯狂加购,系统如何扛住?

🎯 场景引入

你打开手机准备使用设计购物车系统服务。看似简单的操作背后,系统面临三大核心挑战:

  • 挑战一:高并发——如何在百万级 QPS 下保持低延迟?
  • 挑战二:高可用——如何在节点故障时保证服务不中断?
  • 挑战三:数据一致性——如何在分布式环境下保证数据正确?

一、问题背景

1.1 核心挑战

购物车的特点: 1. 读写极高:用户频繁添加、修改数量、删除商品 2. 临时性:大部分商品会被删除或遗忘,只有少数转化为订单 3. 多端同步:手机加购,电脑可见 4. 合并问题:未登录加购 → 登录后合并 核心矛盾: 高频读写 vs 数据持久化 未登录体验 vs 登录后同步 实时价格 vs 缓存性能

1.2 核心需求

需求说明
添加商品加入购物车,支持 SKU 选择
修改数量增减商品数量
删除商品移除购物车中的商品
查看列表展示商品列表、实时价格、总价
离线合并登录后合并未登录时的购物车
多端同步手机、电脑、平板数据一致
结算选择商品生成订单

1.3 容量估算

指标数值
DAU5000 万
购物车操作 QPS~10 万
峰值 QPS(大促)~100 万
平均每人购物车商品数~15
购物车数据总量~7.5 亿条
单条数据大小~200 字节
总存储量~150 GB

二、整体架构

┌─────────────────────────────────────────────────────────────┐ │ 客户端 │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │ │ │ 未登录购物车 │ │ 已登录购物车 │ │ 结算页 │ │ │ │ (LocalStorage)│ │ (服务端) │ │ │ │ │ └──────┬───────┘ └──────┬───────┘ └────────┬─────────┘ │ └─────────┼─────────────────┼────────────────────┼─────────────┘ │ │ │ ▼ ▼ ▼ ┌───────────────────────────────────────────────────────────┐ │ API Gateway │ └───────────────────────┬───────────────────────────────────┘ │ ▼ ┌───────────────────────────────────────────────────────────┐ │ Cart Service(购物车服务) │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────────┐ │ │ │ 增删改查 │ │ 合并服务 │ │ 价格计算 │ │ 结算服务 │ │ │ └────┬─────┘ └────┬─────┘ └────┬─────┘ └──────┬──────┘ │ └───────┼─────────────┼────────────┼──────────────┼─────────┘ │ │ │ │ ▼ ▼ ▼ ▼ ┌─────────────────────────────────────────────────────────┐ │ 存储层 │ │ ┌──────────┐ ┌──────────┐ ┌────────────┐ ┌──────────┐ │ │ │ Redis │ │ MySQL │ │ 商品服务 │ │ 促销服务 │ │ │ │ (主存储) │ │(持久化) │ │ (价格/库存)│ │ (优惠) │ │ │ └──────────┘ └──────────┘ └────────────┘ └──────────┘ │ └─────────────────────────────────────────────────────────┘

三、数据模型设计

// 时间复杂度:O(N),空间复杂度:O(1)

/** * 购物车项 */publicclassCartItem{privateLonguserId;privateLongskuId;privateIntegerquantity;privateBooleanselected;// 是否选中(结算用)privateLongaddTime;// 加入时间// 以下字段不存储,查询时实时获取privatetransientStringskuName;privatetransientLongprice;// 实时价格(分)privatetransientIntegerstock;// 实时库存privatetransientStringimageUrl;}/** * 购物车(Redis Hash 结构) * Key: cart:{userId} * Field: {skuId} * Value: JSON {quantity, selected, addTime} */

四、核心模块实现

4.1 购物车 CRUD 服务

@ServicepublicclassCartService{@AutowiredprivateStringRedisTemplateredisTemplate;@AutowiredprivateProductServiceproductService;privatestaticfinalintMAX_CART_SIZE=100;privatestaticfinalStringCART_KEY_PREFIX="cart:";/** * 添加商品到购物车 */publicCartItemaddItem(LonguserId,LongskuId,intquantity){StringcartKey=CART_KEY_PREFIX+userId;// 1. 检查购物车容量Longsize=redisTemplate.opsForHash().size(cartKey);if(size!=null&&size>=MAX_CART_SIZE){thrownewCartFullException("购物车已满,最多 "+MAX_CART_SIZE+" 件商品");}// 2. 检查商品是否存在且有库存ProductInfoproduct=productService.getProduct(skuId);if(product==null||product.getStock()<=0){thrownewProductUnavailableException("商品不存在或已售罄");}// 3. 如果已在购物车中,数量累加Stringexisting=(String)redisTemplate.opsForHash().get(cartKey,skuId.toString());CartItemDatadata;if(existing!=null){data=JsonUtils.fromJson(existing,CartItemData.class);data.setQuantity(Math.min(data.getQuantity()+quantity,99));// 最多 99 件}else{data=newCartItemData(quantity,true,System.currentTimeMillis());}// 4. 写入 RedisredisTemplate.opsForHash().put(cartKey,skuId.toString(),JsonUtils
http://www.jsqmd.com/news/727046/

相关文章:

  • 用SINET算法给你的图片“找茬”:手把手实现伪装目标检测与可视化标注
  • 如何在3分钟内完成原神成就数据导出:YaeAchievement完整指南
  • 5步实现AI到PSD无损转换:告别手动重建图层的设计工作流
  • 别再硬啃公式了!用Matlab手把手教你给12位SAR ADC建个行为级模型(附完整代码)
  • 告别模拟器时代:Windows系统直接安装APK的5大优势指南
  • 2025届毕业生推荐的十大降AI率助手推荐榜单
  • 如何用 Python 快速接入 Taotoken 并调用多模型 API 提升开发效率
  • WeDLM-7B-Base惊艳效果:多跳推理问题的中间步骤文本续写能力
  • 2026全国二三四五线城市硬笔书法加盟品牌排行实测 - 奔跑123
  • 利用Taotoken构建具备多模型路由策略的智能客服Agent
  • 如何快速解锁B站缓存视频:m4s转换器完整实战指南
  • SteamAutoCrack终极指南:一键免费破解Steam游戏DRM限制
  • Termux图形化踩坑实录:xfce4桌面+VNC连接,从安装到流畅使用的完整避坑指南
  • 别再死记硬背SIFT和ORB了!用Python+OpenCV实战对比,5分钟搞懂特征点匹配到底怎么选
  • 从零开始:使用Rusted PackFile Manager打造你的Total War模组
  • 2026年铅围裙公司最新排名榜单,铅颈套/无铅铅衣/铅防护屏风/射线防护围裙/医用射线防护面罩 - 品牌策略师
  • 从PW5100到CH32:聊聊自制STM32核心板供电方案的选择与那些“烧钱”的教训
  • UnityExplorer终极指南:游戏运行时调试与修改的完整解决方案
  • 自动驾驶算法岗第一课:手把手教你理解Apollo中的角度归一化(附C++代码对比)
  • 通过Taotoken CLI一键配置团队开发环境与模型密钥
  • 【航海软件】海洋船舶可视化仿真神器来了!直接带领船舶仿真进入数字孪生时代!
  • **Apple Intelligence**:该AI系统于WWDC 2024正式发布,是iOS 18/macOS Sequoia/iPadOS 18的核心新增功能
  • 5分钟快速上手:用particles.js为你的网站添加惊艳粒子特效
  • PHP 9.0异步架构下AI机器人响应延迟突增300ms?用strace+phpspy+Prometheus定位真实瓶颈,现在就查!
  • 为Claude Code编程助手配置Taotoken作为后端模型提供商
  • 在 Claude Code 中配置 Taotoken 作为 Anthropic 兼容模型提供商
  • Unity面试官最爱问的C#内存管理:从IL到GC,一次讲透托管与非托管代码
  • 别墅主卧做套房,别只盯着衣帽间,这几个功能区才是提升幸福感的关键
  • 初创公司如何利用 Taotoken 的统一 API 快速验证多个 AI 模型效果
  • 通过 Taotoken CLI 工具一键配置团队统一的开发环境与模型密钥