# aidoweb2 **Repository Path**: mythink/aidoweb2 ## Basic Information - **Project Name**: aidoweb2 - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-11-21 - **Last Updated**: 2025-11-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 高并发秒杀系统设计方案 (High Concurrency Seckill Design) ## 1. 项目背景 本项目旨在开发一个能够支撑 **10,000 QPS**,商品数量 **150,000** 的高并发抢购(秒杀)微应用。采用前后端分离架构,前端使用 Vue.js,后端使用 Spring Boot,数据库为 MySQL。 ## 2. 系统架构 采用经典的微服务分层架构: - **客户端 (Client)**: Vue.js SPA,静态资源部署在 CDN。 - **网关层 (Gateway)**: Nginx 负责负载均衡、动静分离和初步限流。 - **应用层 (Application)**: Spring Boot 微服务,处理业务逻辑。 - **缓存层 (Cache)**: Redis Cluster,负责热点数据缓存、库存预热、原子扣减。 - **消息队列 (Message Queue)**: RabbitMQ,负责削峰填谷,异步下单。 - **数据库 (Database)**: MySQL,负责最终数据持久化。 ## 3. 高并发解决方案 ### 3.1 前端优化 - **页面静态化**: 将秒杀页面HTML、CSS、JS 缓存在 CDN,减少服务器带宽压力。 - **按钮控制**: 用户点击“立即抢购”后,按钮立即置灰(Disable),防止用户重复点击提交请求。 - **本地限流**: 在 JS 层限制请求发送频率。 ### 3.2 服务端优化 - **Redis 预减库存**: - 秒杀开始前,将商品库存预热加载到 Redis 中。 - 请求到达时,利用 Redis 的 `decr` 或 Lua 脚本进行原子扣减。 - 如果 Redis 库存不足,直接返回秒杀结束,拦截大部分流量,保护数据库。 - **Lua 脚本保证原子性**: 使用 Lua 脚本封装“读取库存-判断库存-扣减库存”的操作,确保在高并发下的原子性。 - **内存标记**: 在 JVM 本地维护一个 `Map` 标记,如果 Redis 库存已空,直接在 JVM 层拦截,减少对 Redis 的访问。 ### 3.3 异步下单 (削峰填谷) - **RabbitMQ**: - 库存扣减成功后,不直接操作数据库,而是发送一条消息到 RabbitMQ。 - 消息包含用户ID、商品ID等信息。 - 立即返回给前端“排队中”状态。 - **消费者 (Consumer)**: - 监听队列,从队列中获取消息。 - 执行数据库层面的下单操作(写入订单表、扣减数据库库存)。 - 由于数据库操作被异步化且由队列控制速率,数据库不会被瞬时流量击垮。 ### 3.4 数据库优化 - **唯一索引**: 在秒杀订单表中建立 `(user_id, goods_id)` 唯一索引,防止同一用户重复购买。 - **乐观锁**: 虽然有 Redis 预减,但数据库扣减时仍可加上 `stock > 0` 的条件作为兜底。 ### 3.5 安全与限流 - **接口隐藏**: 秒杀地址动态生成,防止脚本提前刷接口。 - **验证码**: 引入数学公式验证码,拉长请求时间,削减瞬时峰值。 - **限流 (Rate Limiting)**: 使用 Guava RateLimiter (令牌桶) 或 Redis (漏桶) 在网关或拦截器层进行全局限流。 ## 4. 服务器配置与估算 **目标**: QPS 10,000 ### 4.1 应用服务器 (Spring Boot) - **单机估算**: 一个标准的 Spring Boot 节点(4核 8G),在经过 Tomcat 调优(线程池、连接数)和业务逻辑优化(主要是 Redis 操作)后,保守估计能处理 **1,000 - 1,500 QPS**。 - **节点数量**: 为了稳承载 10,000 QPS,并预留冗余(防止单点故障),建议部署 **8 - 10 台** 应用服务器。 - **配置**: 4 Core CPU, 8GB RAM, Gigabit Network. ### 4.2 缓存服务器 (Redis) - **性能**: Redis 单机理论可达 100,000 QPS,但考虑到网络开销和 Lua 脚本执行时间,单机处理 10,000 QPS 绰绰有余。 - **高可用**: 建议使用 **Redis Cluster (3主3从)** 或 **Sentinel (1主2从)** 模式,防止单点故障。 - **配置**: 8 Core CPU, 16GB RAM (内存取决于商品和用户量,15w商品+用户状态占用不大). ### 4.3 消息队列 (RabbitMQ) - **性能**: RabbitMQ 单机吞吐量在万级以上。 - **配置**: 建议 **Cluster 模式 (至少2节点)** 保证高可用。 - **配置**: 4 Core CPU, 8GB RAM. ### 4.4 数据库 (MySQL) - **压力**: 经过 Redis 和 MQ 削峰后,写库压力被平滑处理,QPS 不会直接冲击 DB。 - **配置**: **Master-Slave (1主1从)**,主库负责写,从库负责读(如果业务有查询需求)。 - **配置**: 8 Core CPU, 16GB RAM, SSD (关键). ## 5. 数据库设计 (Schema) ### 5.1 秒杀商品表 (seckill_goods) ```sql CREATE TABLE `seckill_goods` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `goods_id` bigint(20) DEFAULT NULL COMMENT '商品ID', `seckill_price` decimal(10,2) DEFAULT '0.00' COMMENT '秒杀价', `stock_count` int(11) DEFAULT NULL COMMENT '库存数量', `start_date` datetime DEFAULT NULL COMMENT '秒杀开始时间', `end_date` datetime DEFAULT NULL COMMENT '秒杀结束时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ``` ### 5.2 秒杀订单表 (seckill_order) ```sql CREATE TABLE `seckill_order` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `user_id` bigint(20) DEFAULT NULL COMMENT '用户ID', `order_id` bigint(20) DEFAULT NULL COMMENT '订单ID', `goods_id` bigint(20) DEFAULT NULL COMMENT '商品ID', PRIMARY KEY (`id`), UNIQUE KEY `u_uid_gid` (`user_id`,`goods_id`) USING BTREE COMMENT '用户商品唯一索引' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ``` ## 6. 接口设计 1. **获取秒杀地址**: `GET /seckill/path` 2. **执行秒杀**: `POST /seckill/{path}/do_seckill` 3. **查询秒杀结果**: `GET /seckill/result` (轮询)