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

面试基础---如何设计一个高并发的抢购系统(电商)

如何设计一个高并发的抢购系统?

在大型电商平台,抢购系统面临极端的并发挑战,例如“双十一”“秒杀”等场景。为了应对百万级 QPS,我们需要一个 高可用、高并发、低延迟、强一致性 的架构。以下是 实际项目经验,深入拆解设计方案。


1. 业务分析

🔹 场景描述

  • 短时间内大量用户请求,流量峰值可达百万 QPS
  • 库存有限,如 5000 件商品,需确保不超卖
  • 避免数据库崩溃,减少高并发写入

🔹 主要挑战

如何应对高并发? 防止流量直接冲击数据库
如何保证库存一致性? 避免超卖和库存异常
如何提升查询效率? 提高秒杀成功率
如何削峰填谷? 平滑流量,保护核心系统


2. 架构设计

[用户] -> [CDN] -> [Nginx 网关] -> [限流 & 降级] -> [缓存层(Redis)] -> [消息队列(MQ)] -> [数据库]
组件作用
CDN + Nginx 负载均衡缓存静态资源,减少请求压力
限流层限制单个用户请求,防止恶意刷单
Redis 预加载库存99% 读请求在 Redis 层完成
RabbitMQ / Kafka削峰填谷,异步订单处理
MySQL 分库分表避免单表超大,影响性能

3. 技术方案

🔹 1. 限流:防止瞬时流量击穿

  • Nginx 限流(基于 IP/用户)
  • Redis 滑动窗口限流
  • Java Guava RateLimiter(令牌桶算法)

Redis 限流 Lua 脚本

local key = "seckill_limit:" .. KEYS[1]
local limit = tonumber(ARGV[1])
local current = tonumber(redis.call("get", key) or "0")

if current + 1 > limit then
    return 0  -- 限流
else
    redis.call("incr", key)
    redis.call("expire", key, 1)
    return 1  -- 通过
end

🔹 2. 预减库存(缓存抗压)

思路:库存放入 Redis,抢购前先减 Redis,减少数据库查询压力。

Redis 预加载库存

SET seckill_stock_1001 5000

Redis 预减库存

Long stock = redisTemplate.decrement("seckill_stock_1001");
if (stock < 0) {
    redisTemplate.increment("seckill_stock_1001");  // 回滚
    return "库存不足";
}

库存回滚(订单超时未支付)

  • 订单 10 分钟未支付,恢复库存
  • RabbitMQ 死信队列触发库存回滚

🔹 3. 防止超卖(双层校验)

  1. Redis 预减库存
  2. MySQL 行锁最终确认
UPDATE product_stock SET stock = stock - 1 WHERE product_id = 1001 AND stock > 0;

使用 CAS 保证原子性

boolean success = redisTemplate.execute(new DefaultRedisScript<>(luaScript, Boolean.class),
    Collections.singletonList("seckill_stock_1001"), "1");
if (!success) {
    return "抢购失败";
}

🔹 4. 消息队列(异步削峰)

  • 防止订单系统被高并发击穿
  • RabbitMQ / Kafka 进行削峰,异步写订单

消息生产者

rabbitTemplate.convertAndSend("seckillQueue", new OrderMessage(userId, productId));

消息消费者

@RabbitListener(queues = "seckillQueue")
public void handleSeckillOrder(OrderMessage message) {
    productStockService.reduceStock(message.getProductId());
    orderService.createOrder(message.getUserId(), message.getProductId());
}

🔹 5. 分库分表(数据库优化)

方案优化效果
按时间分库order_202401order_202402
按用户 ID 分表ShardingSphere 分片
索引优化product_id + order_time
CREATE TABLE seckill_order (
    id BIGINT PRIMARY KEY,
    user_id BIGINT,
    product_id BIGINT,
    order_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_product_time (product_id, order_time)
);

4. 实战案例

📌 项目背景

某电商平台 秒杀 iPhone 15,5000 件库存,峰值 QPS 100w+,最终订单无超卖。

📌 方案落地

  1. Redis 预热库存:95% 请求在缓存层完成。
  2. 限流策略:滑动窗口 + 令牌桶防止刷单。
  3. 消息队列削峰:订单落库提升 5 倍吞吐量。
  4. 最终一致性:RabbitMQ + 事务确保库存和订单一致。

📌 结果

系统无宕机,QPS 达 100w+
库存精准控制,无超卖
订单延迟 <50ms,用户体验良好


5. 进一步优化

优化点方案
防止缓存穿透布隆过滤器
降低 MySQL 压力Binlog + ES 查询
订单支付超时处理RabbitMQ 死信队列
系统高可用Redis 哨兵 + MySQL 主从

6. 总结

核心思路

  1. 限流(Nginx / Redis) 保护数据库
  2. 缓存预热(Redis 预减库存) 提升秒杀效率
  3. 消息队列(RabbitMQ) 削峰填谷,异步处理订单
  4. 数据库优化(分库分表 + 索引) 提升吞吐量
  5. 最终一致性(事务 + 双写校验) 确保库存精准

💡 面试 Tips:

  • 结合实战经验,描述优化点(如 QPS 提升 5 倍,库存误差<1‰)
  • 突出系统稳定性,讲清限流、削峰、数据库优化策略
  • 深入问答准备:限流算法、Redis 崩溃时处理方案、分布式事务

http://www.kler.cn/a/553782.html

相关文章:

  • Matlab写入点云数据到Rosbag
  • 解压软件手机版推荐:手机端高效解压工具
  • Maven 与 Docker 集成:构建 Docker 镜像并与容器化应用集成
  • 多模态大语言模型(MLLMs)如何重塑和变革计算机视觉?
  • 宇树机器人G1 SDK实战和交付
  • css引入方式
  • CentOS查看IP地址
  • Maven——Maven开发经验总结(1)
  • [数据结构]二叉搜索树详解
  • C++ Primer 类的作用域
  • 探索低空,旅游景区无人机应用技术详解
  • ​ ​rust学习四、控制语句
  • Java流星雨
  • (蓝桥杯——10. 小郑做志愿者)洛斯里克城志愿者问题详解
  • 数据结构-----双向链表
  • 面试知识点2
  • React useState 和 useEffect 使用坑点注意总结
  • 【微信小程序】订阅消息
  • 【DeepSeek服务器部署全攻略】Linux服务器部署DeepSeek R1模型、实现API调用、搭建Web页面以及专属知识库
  • 【数据挖掘】ARFF格式与数据收集