跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava算法

设计支持万人并发抢购的秒杀系统架构方案

综述由AI生成探讨了支持万人并发抢购的秒杀系统设计方案。核心涵盖分层架构以隔离流量,利用 Redis 原子操作与 Lua 脚本解决超卖问题,通过消息队列实现削峰填谷。文章详细介绍了多级缓存策略、限流降级熔断机制以及监控告警体系,并补充了面试中关于秒杀设计的回答思路,强调动静分离、异步处理与最终一致性保障。

安卓系统发布于 2026/1/15更新于 2026/6/311 浏览
设计支持万人并发抢购的秒杀系统架构方案

设计支持万人并发抢购的秒杀系统架构方案

一、系统架构设计

1. 分层架构

一个健壮的秒杀系统通常采用分层处理策略,从客户端到数据层逐级过滤流量:

客户端层 → 接入层 → 业务服务层 → 数据层
限流      缓存       队列        数据库

2. 具体组件

  • 客户端:静态资源通过 CDN 分发,倒计时校准防止时间篡改,前端防重复提交。
  • 接入层:使用 Nginx+Lua 或 OpenResty 进行第一道限流和静态缓存。
  • 业务层:
    • 无状态秒杀服务集群,便于弹性伸缩。
    • 消息队列(Kafka/RocketMQ)用于削峰填谷。
    • Redis Cluster 缓存集群处理热点库存。
  • 数据层:
    • 主从数据库实现读写分离。
    • 分库分表策略按商品 ID 或时间片拆分。

二、核心问题解决方案

1. 超卖问题

方案一:Redis 原子操作

利用 Lua 脚本保证检查与扣减的原子性,避免多线程竞争。

local stock = tonumber(redis.call('GET', KEYS[1]))
if stock and stock > 0 then
    redis.call('DECR', KEYS[1])
    return 1
end
return 0
方案二:数据库乐观锁

在 SQL 层面增加版本号控制,确保并发更新时的数据一致性。

UPDATE products SET stock = stock - 1, version = version + 1 
WHERE id = ? AND stock > 0 AND version = ?
方案三:预扣库存

先扣减 Redis 库存,再异步同步至数据库。若 Redis 扣减失败则回滚。

public boolean preDeductStock(String productId, int count) {
    String key = "seckill:stock:" + productId;
    Long remaining = redisTemplate.opsForValue().decrement(key, count);
    if (remaining >= 0) {
        sendStockDeductMessage(productId, count); // 发送 MQ 异步扣减 DB
        return true;
    } else {
        redisTemplate.opsForValue().increment(key, count); // 库存不足回滚
        return false;
    }
}

2. 高并发请求处理

2.1 流量削峰

将同步请求转为异步处理,用户提交后立即返回排队状态,后端慢慢消费。

@Component
public class SeckillService {
    @Autowired
    private RocketMQTemplate mqTemplate;

    public SeckillResult seckill(SeckillRequest request) {
        if (!validate(request)) {
            return SeckillResult.fail("校验失败");
        }
        String requestId = generateRequestId(request);
        // 请求入队,立即返回
        mqTemplate.sendOneWay("seckill-topic", MessageBuilder.withPayload(request).build());
        return SeckillResult.processing(requestId);
    }
}
2.2 分层过滤

通过多级校验逐步减少进入核心逻辑的请求量:

所有请求 → 合法性校验 → 库存校验 → 频率控制 → 实际下单
100 万     → 50 万       → 10 万      → 5 万      → 1 万

3. 系统性能优化

3.1 缓存策略

采用多级缓存架构,减轻数据库压力:

  • 一级缓存:JVM 本地缓存(Caffeine),存储热点商品详情。
  • 二级缓存:Redis 集群,存储库存信息与布隆过滤器。
  • 三级缓存:数据库,保证最终一致性。
3.2 读多写少优化

活动开始前预热商品信息,避免冷启动冲击。

@Service
public class CacheWarmUpService {
    @PostConstruct
    public void warmUpSeckillProducts() {
        List<Product> hotProducts = loadHotProducts();
        for (Product product : hotProducts) {
            redisTemplate.opsForValue().set("stock:" + product.getId(), product.getStock());
            redisTemplate.opsForValue().set("product:" + product.getId(), JSON.toJSONString(product));
            bloomFilter.add(product.getId());
        }
    }
}

4. 详细实现方案

4.1 秒杀流程

整合风险拦截、布隆过滤、库存判断及订单生成,形成完整闭环。

public Response processSeckill(String userId, String productId) {
    // 1. 恶意请求拦截
    if (!checkRisk(userId)) {
        return Response.error("访问过于频繁");
    }
    // 2. 布隆过滤器快速判断
    if (!bloomFilter.contains(productId)) {
        return Response.error("商品不存在");
    }
    // 3. 内存标记已售罄
    if (soldOutFlags.get(productId)) {
        return Response.error("已售罄");
    }
    // 4. Redis 原子扣减库存
    if (!deductStockInRedis(productId)) {
        soldOutFlags.put(productId, true);
        return Response.error("库存不足");
    }
    // 5. 生成订单 ID(雪花算法)
    String orderId = snowflake.generate();
    // 6. 订单信息入队
    mq.send(OrderDTO.builder()
        .orderId(orderId)
        .userId(userId)
        .productId(productId)
        .time(System.currentTimeMillis())
        .build());
    // 7. 返回排队中
    return Response.success("排队中", orderId);
}
4.2 库存同步方案

后台服务消费 MQ 消息,异步更新数据库并执行对账任务。

@Component
@Slf4j
public class StockSyncService {
    @Transactional
    public void syncStockToDB(String productId, int count) {
        try {
            boolean success = productDAO.deductStock(productId, count);
            if (success) {
                redisTemplate.opsForValue().set("stock_final:" + productId, getDBStock(productId));
                soldOutCache.remove(productId);
            }
        } catch (Exception e) {
            log.error("库存同步失败", e);
            alertService.sendAlert(e);
        }
    }

    @Scheduled(cron = "0 */5 * * * ?")
    public void stockReconciliation() {
        List<Product> products = productDAO.getAllSeckillProducts();
        for (Product product : products) {
            Integer redisStock = getRedisStock(product.getId());
            Integer dbStock = product.getStock();
            if (!Objects.equals(redisStock, dbStock)) {
                log.warn("库存不一致:productId={}, redis={}, db={}", product.getId(), redisStock, dbStock);
                fixStockInconsistency(product.getId(), dbStock);
            }
        }
    }
}

三、高可用保障

1. 限流降级策略

多维度配置限流规则,保护核心服务不被压垮:

  • 用户维度:每个用户 10 次/分钟。
  • IP 维度:每个 IP 1000 次/分钟。
  • 商品维度:每个商品 10000 次/分钟。
  • 总 QPS:系统最大承受 50000 QPS。

2. 熔断降级

当依赖服务响应过慢时自动熔断,防止雪崩。

@RestController
@Slf4j
public class SeckillController {
    @GetMapping("/seckill/{productId}")
    @HystrixCommand(
        fallbackMethod = "seckillFallback",
        commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000"),
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "20")
        }
    )
    public Response seckill(@PathVariable String productId, @RequestParam String userId) {
        return seckillService.process(userId, productId);
    }

    public Response seckillFallback(String productId, String userId) {
        return Response.error("系统繁忙,请稍后重试");
    }
}

四、监控与告警

1. 关键监控指标

  • 系统层面:QPS、RT、错误率、CPU/内存使用率。
  • 应用层面:库存扣减成功率、消息堆积量。
  • 业务层面:抢购成功率、用户排队时长。

2. 监控实现

使用 Micrometer 等工具记录关键指标。

@Component
public class SeckillMonitor {
    private final MeterRegistry meterRegistry;

    public void recordSeckill(String productId, boolean success, long cost) {
        meterRegistry.counter("seckill.requests.total").increment();
        if (success) {
            meterRegistry.counter("seckill.success.total").increment();
        } else {
            meterRegistry.counter("seckill.fail.total").increment();
        }
        meterRegistry.timer("seckill.process.time")
            .record(cost, TimeUnit.MILLISECONDS);
        meterRegistry.gauge("seckill.stock." + productId, getCurrentStock(productId));
    }
}

五、部署与扩展

1. 弹性扩展策略

  • 水平扩展:无状态服务可快速扩容。
  • 自动伸缩:基于 CPU 使用率或 QPS 自动扩缩容。
  • 异地多活:重要业务支持多机房部署。

2. 压测方案

  • 场景 1:库存预热,10 万用户同时抢 1 万商品。
  • 场景 2:持续高压,5 万 QPS 持续 5 分钟。
  • 场景 3:峰值冲击,瞬间 20 万 QPS。
  • 目标:成功率 >99.9%,平均 RT <100ms,错误率 <0.1%。

六、安全考虑

  • 防刷机制:验证码(峰值时降级)、设备指纹、行为分析。
  • 数据安全:关键数据加密、操作日志记录、防篡改校验。

七、实战复盘:面试视角下的秒杀设计

如果在面试中被问到如何设计秒杀系统,建议从架构、核心难点、兜底策略三个维度展开:

  1. 架构设计上动静分离、分层削峰 静态资源推送到 CDN,网关层做限流和恶意拦截。核心下单逻辑后置,请求进入消息队列,实现削峰填谷。服务独立部署,避免影响商城其他功能。

  2. 解决超卖与高并发 库存预热到 Redis,使用 DECR 或 Lua 脚本保证原子性扣减。数据库作为最终一致性存储,通过异步对账修复差异。应对高并发时,除了限流,还要做热点 Key 散列和服务无状态化扩容。

  3. 细节与兜底 前端加入计算型验证码,下单前校验资格。用户提交后返回排队 ID 轮询结果。建立定时对账任务核对 Redis、DB 库存和订单状态。若 Redis 或数据库异常,要有熔断机制,快速降级返回售罄页面。

总结来说,设计思路是:前端限流拦截,请求队列削峰;Redis 原子扣减防超卖;服务无状态化应对高并发;再通过异步、对账等手段保证最终一致性和用户体验。

目录

  1. 设计支持万人并发抢购的秒杀系统架构方案
  2. 一、系统架构设计
  3. 1. 分层架构
  4. 2. 具体组件
  5. 二、核心问题解决方案
  6. 1. 超卖问题
  7. 方案一:Redis 原子操作
  8. 方案二:数据库乐观锁
  9. 方案三:预扣库存
  10. 2. 高并发请求处理
  11. 2.1 流量削峰
  12. 2.2 分层过滤
  13. 3. 系统性能优化
  14. 3.1 缓存策略
  15. 3.2 读多写少优化
  16. 4. 详细实现方案
  17. 4.1 秒杀流程
  18. 4.2 库存同步方案
  19. 三、高可用保障
  20. 1. 限流降级策略
  21. 2. 熔断降级
  22. 四、监控与告警
  23. 1. 关键监控指标
  24. 2. 监控实现
  25. 五、部署与扩展
  26. 1. 弹性扩展策略
  27. 2. 压测方案
  28. 六、安全考虑
  29. 七、实战复盘:面试视角下的秒杀设计
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • SpringBoot 结合 Redis+Caffeine 多级缓存架构实践
  • Trae Agent 利用 MCP Tools 实现 Gitee 自动化管理
  • C++ 类与对象基础:封装、实例化与 this 指针详解
  • 耳机阻抗与前端适配:32Ω至 300Ω耳机的推力需求解析
  • Java 常用消息中间件深度解析:特性、架构与适用场景
  • Spring IoC 与依赖注入核心原理
  • C++ STL set 系列:底层原理、核心接口与实战场景
  • LazyLLM 多 Agent 应用全流程实践:源码部署与可视化调试
  • RabbitMQ C++ 消息队列组件与 AMQP-CPP 使用
  • SQLSugar 封装原理详解:架构与核心模块底层实现
  • 高鋒集團與 Web3Labs:以資本與生態賦能傳統企業 Web3 轉型
  • 腾讯混元图像 3.0 图生图模型开源,LMArena 评测跻身全球第一梯队
  • NTC 热敏电阻温度测量算法与 STM32 实现
  • STM32 HAL 库软件 IIC 驱动 AT24C02/AT24C32 时序与读写
  • 跨国企业 Git 连接困境分析与智能代理配置方案
  • 前端骨架屏实现详解:Vue、React、Angular、jQuery 及小程序实践
  • 基于 SpringAI Alibaba 开发大模型智能体,支持基础版和多模式
  • RMBG-2.0 企业级集成:API 封装、Flask 后端与前端拖拽上传方案
  • 多模态 Agent 图像识别 Skills 开发实战:Web 全栈图像处理方案
  • WordPress 基础配置与 Spring Boot 接口开发实战记录

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online