news 2026/5/1 9:49:34

购物车该存 Redis 还是 MySQL?架构师教你设计一个“高并发、防丢失”的购物车系统

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
购物车该存 Redis 还是 MySQL?架构师教你设计一个“高并发、防丢失”的购物车系统

🛒 前言:小小的购物车,大大的坑

在面试中,我最喜欢问候选人一个问题:“设计一个京东/淘宝级别的购物车,数据应该存在哪里?”

  • 回答 A:“存在 Cookie 里,省服务器资源。” ——。用户换个手机登录,购物车空了,体验极差。
  • 回答 B:“存在 MySQL 里,安全。” ——。双 11 千万级并发,每次加购都写库,数据库直接火葬场。
  • 回答 C:“存在 Redis 里,快。” ——对了一半。Redis 挂了怎么办?数据丢失会导致严重的客诉。

真正的购物车系统,是一个**“浏览器 + Redis + MySQL + 消息队列”**的混合架构。今天我们就来拆解这个架构是如何一步步搭建出来的。


🥈 方案一:纯数据库架构 (早期/低流量)

在创业初期,流量不大,直接用 MySQL 也是没问题的。

表结构设计:

CREATETABLE`cart_item`(`id`bigintNOTNULLAUTO_INCREMENT,`user_id`bigintNOTNULLCOMMENT'用户ID',`sku_id`bigintNOTNULLCOMMENT'商品ID',`count`intNOTNULLCOMMENT'数量',`checked`tinyintDEFAULT1COMMENT'是否勾选',`update_time`datetime,PRIMARYKEY(`id`),UNIQUEKEY`idx_user_sku`(`user_id`,`sku_id`));

致命缺陷:
购物车是**“读写极高频”**的业务。
用户反复加减数量、勾选商品,如果每一次操作都去 Update 数据库,数据库的TPS (Transcation Per Second)撑不住。而且这属于“临时数据”,占用大量宝贵的数据库存储空间。


🥇 方案二:纯 Redis 架构 (中等流量)

为了快,我们将数据全部迁移到 Redis。
数据结构选型:Hash

  • Key:cart:{userId}
  • Field:skuId
  • Value: JSON 字符串 (包含数量、勾选状态、加入时间)

Redis 命令演示:

# 添加商品 1001,数量 2HSET cart:88881001"{'count':2, 'checked':1}"# 增加商品数量HINCRBY cart:888810011# 获取购物车所有商品HGETALL cart:8888# 删除商品HDEL cart:88881001

优点:性能极其彪悍,支持 10 万+ QPS。
缺点:Redis 内存贵。且 RDB/AOF 持久化有滞后,极端宕机情况下会丢数据(虽然购物车数据丢失通常可接受,但对于大厂这是 P0 级事故)。


💎 方案三:终极混合架构 (Cookie + Redis + MySQL + MQ)

这是目前主流电商(淘宝、京东)的通用架构。

1. 核心策略
  • 未登录状态:数据保存在客户端Cookie/LocalStorage中。
  • 登录状态:数据保存在Redis中(热数据)。
  • 持久化:通过MQ 异步将 Redis 的变更写入MySQL(冷数据备份,防丢失,做数据分析)。
2. 关键流程:登录合并 (Merge)

这是最复杂的逻辑。当用户在“未登录”时往 Cookie 加了 3 个商品,然后点击“登录”。
系统必须将 Cookie 里的数据 + Redis 里原有的数据进行合并。

架构流程图:

异步持久化
登录合并流程
登录态判断
未登录
已登录
读取临时购物车
读取原有购物车
1. 合并逻辑
2. 清空 Cookie
发送变更消息
削峰填谷
批量写入
RocketMQ / Kafka
DB 同步服务
MySQL 备份库
购物车合并服务
用户登录动作
用户操作
写入 Cookie / LocalStorage
API 网关
操作 Redis Hash

🛠️ 核心代码实战:Redis 封装

我们使用 Spring Boot + RedisTemplate 来实现核心操作。

@ServicepublicclassCartService{@AutowiredprivateStringRedisTemplateredisTemplate;privatestaticfinalStringCART_PREFIX="cart:";/** * 添加购物车 */publicvoidaddCart(LonguserId,LongskuId,Integercount){Stringkey=CART_PREFIX+userId;BoundHashOperations<String,Object,Object>cartOps=redisTemplate.boundHashOps(key);StringskuIdStr=skuId.toString();// 1. 判断商品是否存在if(cartOps.hasKey(skuIdStr)){// 2. 存在则累加数量Stringjson=(String)cartOps.get(skuIdStr);CartItemitem=JSON.parseObject(json,CartItem.class);item.setCount(item.getCount()+count);cartOps.put(skuIdStr,JSON.toJSONString(item));}else{// 3. 不存在则新增CartItemnewItem=newCartItem(skuId,count);cartOps.put(skuIdStr,JSON.toJSONString(newItem));}// 4. 发送 MQ 消息做异步持久化 (伪代码)// producer.send("cart_update_topic", new CartUpdateEvent(userId, skuId));}/** * 登录合并逻辑 */publicvoidmergeCart(LonguserId,List<CartItem>cookieItems){if(CollectionUtils.isEmpty(cookieItems))return;for(CartItemcookieItem:cookieItems){addCart(userId,cookieItem.getSkuId(),cookieItem.getCount());}// 合并完成后,通知前端清除 Cookie}}

🧐 进阶思考:Redis 存满了怎么办?

购物车数据有一个特点:僵尸数据多。很多用户几年前加的商品还在购物车里。
如果所有数据都堆在 Redis,内存会爆炸。

优化策略:LRU + 自动过期

  1. 设置 TTL:给cart:{userId}设置过期时间(例如 30 天)。
  2. 自动续期:每次用户查看购物车或加购时,重置 TTL 为 30 天。
  3. 兜底:如果 Redis Key 过期了(用户 30 天没来了),再次访问时,从MySQL把数据加载回 Redis(缓存预热)。

这样既保证了活跃用户的极速体验,又节省了昂贵的 Redis 内存。


📝 总结

设计购物车系统的 4 个金科玉律:

  1. 读写分离:Redis 抗并发,MySQL 兜底。
  2. 异步写入:使用 MQ 解耦,不要让 DB 拖慢加购速度。
  3. 端云协同:未登录存前端,登录后做合并。
  4. 冷热分离:利用 TTL 清理僵尸购物车。

架构没有最好的,只有最合适的。理解了这套逻辑,你就能轻松应对大多数电商面试题。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 9:40:04

焦距区域和光纤耦合容差

用于将光耦合到单模光纤的光学系统的详细分析和设计依赖于焦距区域中场的精确计算。在VirtualLab Fusion中&#xff0c;可以在例如焦距区域的任意平面上和纵向区域内计算电磁场信息。这为随后的光纤耦合效率计算奠定了坚实的基础。灵活的焦距区域分析能进一步对光学系统中光学部…

作者头像 李华
网站建设 2026/5/1 6:07:29

人机交互(如 VR 手柄追踪、光标移动、手势识别)的滤波算法

这段代码实现了一个 One Euro Filter&#xff08;一欧元滤波器&#xff09;。1. 原理简述One Euro Filter 是一种主要用于人机交互&#xff08;如 VR 手柄追踪、光标移动、手势识别&#xff09;的算法。它解决了一个核心矛盾&#xff1a;抖动&#xff08;Jitter&#xff09;与延…

作者头像 李华
网站建设 2026/5/1 5:00:51

Excalidraw实战教程:如何用自然语言快速生成技术架构图?

Excalidraw实战&#xff1a;用自然语言一键生成技术架构图 在一次跨时区的远程架构评审会上&#xff0c;团队卡在了最基础的问题上——产品经理口述的“用户请求先过网关&#xff0c;再进服务集群”被后端理解为南北向流量模型&#xff0c;而前端却画出了东西向服务网格。这种因…

作者头像 李华
网站建设 2026/5/1 5:01:05

AutoGPT与Notion联动教程:自动整理笔记与知识库更新

AutoGPT与Notion联动&#xff1a;构建自主更新的知识库系统 在信息爆炸的时代&#xff0c;知识工作者每天都在面对海量碎片化内容——论文、博客、课程、会议记录……如何将这些零散信息高效整合成可检索、可复用的知识资产&#xff0c;已成为提升个人与团队生产力的核心挑战。…

作者头像 李华
网站建设 2026/5/1 5:04:12

gLabels-Qt:打造专业标签设计的现代化解决方案

gLabels-Qt&#xff1a;打造专业标签设计的现代化解决方案 【免费下载链接】glabels-qt gLabels Label Designer (Qt/C) 项目地址: https://gitcode.com/gh_mirrors/gl/glabels-qt 在数字化办公日益普及的今天&#xff0c;标签设计已成为企业日常运营中不可或缺的一环。…

作者头像 李华