news 2025/12/25 0:58:50

购物车该存 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进行投诉反馈,一经查实,立即删除!
网站建设 2025/12/16 11:03:56

桌宠交互性能优化实战:如何解决触摸延迟与动画卡顿问题

桌宠交互性能优化实战&#xff1a;如何解决触摸延迟与动画卡顿问题 【免费下载链接】VPet 虚拟桌宠模拟器 一个开源的桌宠软件, 可以内置到任何WPF应用程序 项目地址: https://gitcode.com/GitHub_Trending/vp/VPet 在虚拟宠物应用中&#xff0c;触摸反馈的即时性和动画…

作者头像 李华
网站建设 2025/12/21 14:36:31

Zotero AI插件终极指南:3分钟快速部署智能文献助手

Zotero AI插件终极指南&#xff1a;3分钟快速部署智能文献助手 【免费下载链接】papersgpt-for-zotero Zotero chat PDF with DeepSeek, GPT, ChatGPT, Claude, Gemini 项目地址: https://gitcode.com/gh_mirrors/pa/papersgpt-for-zotero 还在为海量学术文献感到头疼吗…

作者头像 李华
网站建设 2025/12/19 6:12:40

学生党最爱省钱爱创猫AI APP

外卖点出大餐感&#xff0c;网购省出新高度&#xff1a;学生党的精打细算实战手册每个月末&#xff0c;看着账单上那些不起眼的外卖订单和购物记录&#xff0c;是不是总感觉钱不知不觉就“蒸发”了&#xff1f;一杯奶茶、一次凑单、一个“限时秒杀”&#xff0c;积少成多&#…

作者头像 李华
网站建设 2025/12/16 11:03:16

将PDF转化为RAG文件,进行数据清洗

在本地 RAG 系统中使用 Marker&#xff1a;高精度 PDF 到 Markdown 的离线开源解决方案&#xff08;2025 更新&#xff09; 在本地 RAG&#xff08;Retrieval-Augmented Generation&#xff09;系统中&#xff0c;PDF 解析质量是决定最终问答准确率的关键&#xff08;Garbage …

作者头像 李华
网站建设 2025/12/16 11:02:25

Linux内核实时调度:从基础到实战的终极指南

Linux内核实时调度&#xff1a;从基础到实战的终极指南 【免费下载链接】linux-insides-zh Linux 内核揭秘 项目地址: https://gitcode.com/gh_mirrors/li/linux-insides-zh 在当今的嵌入式系统和工业自动化领域&#xff0c;实时性已成为系统设计的核心考量。你是否曾面…

作者头像 李华
网站建设 2025/12/19 17:40:20

大数据领域数据治理的核心要点与实践策略

大数据领域数据治理的核心要点与实践策略 1. 引入与连接 1.1 引人入胜的开场 在当今数字化时代&#xff0c;数据就如同石油一般&#xff0c;是企业和社会发展的重要资源。想象一下&#xff0c;一家大型电商企业&#xff0c;每天都能收集到海量的数据&#xff0c;包括用户的浏览…

作者头像 李华