1. 基于Session的购物车(适合小型单体应用)
-
核心思路:将购物车数据存储在用户会话(Session)中,适用于无需持久化的临时购物车。
-
实现步骤:
- 数据结构 :使用
Map<商品ID, 商品数量>
或自定义CartItem
对象(包含商品ID、数量、选中状态等)。 - 操作逻辑:
- 数据结构 :使用
-
添加商品:检查Session中是否存在购物车,若不存在则初始化;存在则更新商品数量。
-
删除商品:从Session的购物车Map中移除指定商品。
-
合并购物车 :用户登录后,将临时购物车(Session)与用户数据库中的购物车合并。
- 生命周期:购物车数据随Session过期而清除(默认30分钟)。
-
代码示例:
HttpSession session = request.getSession(); Map<Long, Integer> cart = (Map<Long, Integer>) session.getAttribute("cart"); if (cart == null) { cart = new HashMap<>(); session.setAttribute("cart", cart); } cart.put(productId, quantity);
-
优缺点:
- 优点:实现简单,无数据库依赖。
- 缺点:数据易丢失(Session过期或服务器重启);不支持多端同步。
2. 基于数据库的购物车(适合需要持久化的场景)
-
核心思路:将购物车数据持久化到数据库,适用于用户登录后长期保存购物车。
-
数据库设计:
CREATE TABLE cart ( id BIGINT PRIMARY KEY AUTO_INCREMENT, user_id BIGINT NOT NULL, -- 用户ID product_id BIGINT NOT NULL, -- 商品ID quantity INT NOT NULL, -- 商品数量 selected BOOLEAN DEFAULT TRUE, -- 是否选中 create_time TIMESTAMP, update_time TIMESTAMP );
-
实现步骤:
- 添加商品:
-
检查用户购物车中是否已存在该商品:存在则
UPDATE quantity
,否则INSERT
新记录。- 合并购物车:
-
用户登录后,将未登录时的临时购物车(如Cookie或LocalStorage)与数据库购物车合并。
- 性能优化:
-
缓存机制:将购物车数据缓存到Redis,减少数据库查询。
-
批量操作:支持批量添加/删除商品,减少数据库IO。
-
代码示例(MyBatis):
<update id="updateCartQuantity"> UPDATE cart SET quantity = #{quantity}, update_time = NOW() WHERE user_id = #{userId} AND product_id = #{productId} </update>
-
优缺点:
- 优点:数据持久化,支持多端同步。
- 缺点:频繁读写时数据库压力大;需处理高并发场景下的数据一致性。
3. 基于Redis的购物车(适合高并发、分布式场景)
-
核心思路:利用Redis的高性能读写和数据结构(Hash、String)存储购物车。
-
数据结构设计:
- Key :
cart:user:{userId}
- Value :Hash结构,
field
为商品ID,value
为商品数量及其他信息(JSON格式)。
- Key :
-
实现步骤:
-
添加商品:
// 使用Redis Hash存储购物车(Jedis示例) jedis.hset("cart:user:1001", "product_202", "{\"quantity\":2, \"selected\":true}");
-
合并购物车:
-
-
用户登录后,将临时购物车(如Cookie中的商品列表)与Redis中的购物车合并。
- 过期时间:设置Key的过期时间(如7天未操作自动清除)。
-
优缺点:
- 优点:高性能,支持分布式系统;天然支持过期时间。
- 缺点:需处理Redis与数据库的数据同步(如结算时持久化到数据库)。
4. 分布式购物车的进阶设计
- 场景:大型电商系统,需保证高可用、数据一致性和扩展性。
- 核心方案 :
- 读写分离:
- 读操作:优先从Redis读取购物车数据。
- 写操作:先更新Redis,再异步同步到数据库。
2. 数据分片: - 按用户ID哈希分片,将购物车数据分散到多个Redis实例或数据库表中。
3. 商品信息缓存: - 将商品详情(价格、库存)缓存到Redis,避免每次查询数据库。
4. 并发控制: - 使用Redis的
WATCH
命令或分布式锁(Redisson)防止重复提交。
面试回答要点总结
- 根据场景选择技术栈 :
- 临时购物车 → Session或Cookie。
- 持久化需求 → 数据库 + 缓存(Redis)。
- 高并发分布式 → Redis + 异步同步。
- 数据结构设计 :
- 简单场景用
Map
,复杂场景用数据库表或Redis Hash。
- 简单场景用
- 关键问题处理 :
- 合并购物车:登录时合并临时购物车与持久化数据。
- 数据一致性:通过缓存+数据库双写或异步消息队列(如RabbitMQ)保证。
- 性能优化:缓存、批量操作、分库分表。
- 扩展性:分布式架构设计思路(分片、读写分离)。
示例回答 :
"在实现购物车时,我会先明确业务需求。如果是小型系统,可以用Session存储临时购物车;如果需要持久化,则选择数据库存储,并结合Redis缓存提高性能。对于高并发场景,Redis的Hash结构能高效管理购物车商品,同时通过异步同步机制保证数据最终一致性。此外,需处理用户登录前后的购物车合并,以及商品信息变更时的同步问题。"