本文目录导读:

我来为你提供一个完整的高并发秒杀系统设计案例,这是Java面试中最经典的系统设计题目之一。
系统需求分析
核心业务场景
- 限时抢购商品
- 高并发访问(可能达到10万+ QPS)
- 超卖问题必须避免
- 系统需要稳定可靠
核心功能
商品管理:上架、库存管理
2. 秒杀活动:活动配置、时间控制
3. 下单流程:秒杀请求处理
4. 订单系统:订单生成、状态管理
5. 支付系统:支付对接(可选)
架构设计
整体架构图
graph TB
A[客户端] --> B[CDN]
B --> C[负载均衡 Nginx/LVS]
C --> D[Web服务器集群]
D --> E[缓存层 Redis集群]
D --> F[消息队列 RabbitMQ/Kafka]
F --> G[订单服务]
G --> H[数据库 MySQL主从]
E --> H
详细架构设计
┌─────────────────────────────────────────────┐
│ 客户端层 │
│ Web端 / App端 / H5页面 │
└─────────────────┬───────────────────────────┘
│
┌─────────────────▼───────────────────────────┐
│ 接入层 │
│ CDN + 负载均衡 + 网关 + 限流 │
│ (Nginx + Sentinel/Guava RateLimiter) │
└─────────────────┬───────────────────────────┘
│
┌─────────────────▼───────────────────────────┐
│ 业务层 │
│ 秒杀接口 + 订单服务 + 支付服务 │
│ (SpringBoot 集群) │
└─────────────────┬───────────────────────────┘
│
┌─────────────────▼───────────────────────────┐
│ 中间件层 │
│ Redis集群 + MQ队列 + 任务调度 │
└─────────────────┬───────────────────────────┘
│
┌─────────────────▼───────────────────────────┐
│ 数据层 │
│ MySQL主从 + ES + 分库分表 │
└─────────────────────────────────────────────┘
核心技术实现
前端优化
// 1. 静态资源CDN加速
- 商品详情页静态化处理
- 使用CDN分发静态资源
- 按钮置灰,禁止重复提交
// 2. 后端接口动静分离
@Controller
public class SeckillController {
@GetMapping("/seckill/{goodsId}")
public String seckillPage(@PathVariable("goodsId") Long goodsId,
Model model) {
// 静态化页面数据
model.addAttribute("goods", goodsService.getGoodsInfo(goodsId));
model.addAttribute("startTime", seckillService.getStartTime(goodsId));
model.addAttribute("endTime", seckillService.getEndTime(goodsId));
return "seckill";
}
}
缓存设计(Redis)
@Service
public class SeckillService {
@Autowired
private StringRedisTemplate redisTemplate;
// 商品库存缓存Key
private static final String STOCK_KEY = "seckill:stock:";
// 用户购买记录Key
private static final String USER_KEY = "seckill:user:";
// 秒杀结果Key
private static final String RESULT_KEY = "seckill:result:";
/**
* 秒杀核心逻辑
*/
public SeckillResult seckill(Long userId, Long goodsId) {
// 1. 校验用户是否已购买过
if (redisTemplate.hasKey(USER_KEY + userId + ":" + goodsId)) {
return SeckillResult.error("您已参与过秒杀");
}
// 2. 预扣库存(Redis原子操作)
Long stock = redisTemplate.opsForValue()
.decrement(STOCK_KEY + goodsId);
if (stock < 0) {
// 库存不足,回补库存
redisTemplate.opsForValue().increment(STOCK_KEY + goodsId);
return SeckillResult.error("商品已售罄");
}
// 3. 记录用户购买信息
redisTemplate.opsForValue()
.set(USER_KEY + userId + ":" + goodsId, "1", 10, TimeUnit.MINUTES);
// 4. 发送消息到MQ,异步处理订单
sendOrderMessage(userId, goodsId);
return SeckillResult.success("秒杀成功");
}
/**
* 使用Lua脚本确保原子性
*/
public boolean seckillWithLua(Long userId, Long goodsId) {
String script =
"local stock = redis.call('get', KEYS[1])" +
"if tonumber(stock) <= 0 then return 0 end" +
"redis.call('decr', KEYS[1])" +
"redis.call('set', KEYS[2], 1)" +
"return 1";
DefaultRedisScript<Long> redisScript =
new DefaultRedisScript<>(script, Long.class);
Long result = redisTemplate.execute(redisScript,
Arrays.asList(STOCK_KEY + goodsId, USER_KEY + userId + ":" + goodsId));
return result == 1;
}
}
消息队列异步处理
@Slf4j
@Component
public class OrderConsumer {
@Autowired
private OrderService orderService;
/**
* 监听订单消息
*/
@RabbitListener(queues = "seckill.order.queue")
public void handleOrderMessage(SeckillMessage message) {
try {
// 创建订单
Order order = orderService.createOrder(
message.getUserId(),
message.getGoodsId()
);
// 更新库存(数据库最终一致性)
goodsService.updateStock(message.getGoodsId());
// 记录秒杀结果
redisTemplate.opsForValue().set(
RESULT_KEY + message.getUserId() + ":" + message.getGoodsId(),
JSON.toJSONString(order)
);
log.info("订单创建成功: userId={}, orderId={}",
message.getUserId(), order.getId());
} catch (Exception e) {
log.error("订单创建失败", e);
// 失败重试或补偿处理
sendCompensationMessage(message);
}
}
}
分布式锁应用
@Configuration
public class RedissonConfig {
@Bean
public RedissonClient redissonClient() {
Config config = new Config();
config.useSingleServer()
.setAddress("redis://localhost:6379")
.setDatabase(0);
return Redisson.create(config);
}
}
@Service
public class SeckillLockService {
@Autowired
private RedissonClient redissonClient;
public boolean seckillWithLock(Long userId, Long goodsId) {
String lockKey = "seckill:lock:" + goodsId;
RLock lock = redissonClient.getLock(lockKey);
try {
// 尝试获取分布式锁
if (!lock.tryLock(500, 20000, TimeUnit.MILLISECONDS)) {
throw new RuntimeException("系统繁忙,请稍后重试");
}
// 校验库存
int stock = goodsDao.getStock(goodsId);
if (stock <= 0) {
return false;
}
// 扣减库存
goodsDao.decreaseStock(goodsId);
// 创建订单
orderService.createOrder(userId, goodsId);
return true;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
} finally {
lock.unlock();
}
}
}
限流控制
@Component
public class RateLimitInterceptor implements HandlerInterceptor {
private static final Map<String, RateLimiter> RATE_LIMITERS =
new ConcurrentHashMap<>();
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
String uri = request.getRequestURI();
// 每用户每秒最多5个请求
String userId = request.getHeader("userId");
String key = uri + ":" + userId;
RateLimiter rateLimiter = RATE_LIMITERS.computeIfAbsent(
key, k -> RateLimiter.create(5)
);
if (!rateLimiter.tryAcquire()) {
response.setStatus(429);
response.getWriter().write("请求过于频繁");
return false;
}
return true;
}
}
数据库优化设计
数据库表设计
-- 秒杀商品表 CREATE TABLE `seckill_goods` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `goods_name` VARCHAR(100) NOT NULL COMMENT '商品名称', `seckill_price` DECIMAL(10,2) NOT NULL COMMENT '秒杀价格', `original_price` DECIMAL(10,2) NOT NULL COMMENT '原价', `stock_count` INT NOT NULL COMMENT '库存数量', `start_time` DATETIME NOT NULL COMMENT '开始时间', `end_time` DATETIME NOT NULL COMMENT '结束时间', `status` TINYINT NOT NULL DEFAULT 0 COMMENT '状态:0未开始 1进行中 2已结束', `version` INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', PRIMARY KEY (`id`), KEY `idx_start_time` (`start_time`), KEY `idx_end_time` (`end_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 秒杀订单表 CREATE TABLE `seckill_order` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `user_id` BIGINT NOT NULL COMMENT '用户ID', `goods_id` BIGINT NOT NULL COMMENT '商品ID', `order_no` VARCHAR(32) NOT NULL COMMENT '订单号', `seckill_price` DECIMAL(10,2) NOT NULL COMMENT '秒杀价格', `status` TINYINT NOT NULL DEFAULT 0 COMMENT '状态:0待支付 1已支付 2已取消', `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `pay_time` DATETIME DEFAULT NULL COMMENT '支付时间', PRIMARY KEY (`id`), UNIQUE KEY `uk_user_goods` (`user_id`, `goods_id`), KEY `idx_order_no` (`order_no`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
数据库优化策略
// 1. 分库分表设计
// 订单表按用户ID分表
@TableName("seckill_order")
@TableId(type = IdType.AUTO)
public class SeckillOrder {
@TableId(type = IdType.INPUT)
private Long id;
@TableField("user_id")
private Long userId;
// ... 其他字段
}
// 2. 读写分离配置
@Configuration
public class DataSourceConfig {
@Bean
@ConfigurationProperties("spring.datasource.master")
public DataSource masterDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties("spring.datasource.slave")
public DataSource slaveDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
public DynamicDataSource dynamicDataSource() {
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put(DataSourceType.MASTER, masterDataSource());
targetDataSources.put(DataSourceType.SLAVE, slaveDataSource());
return new DynamicDataSource(masterDataSource(), targetDataSources);
}
}
流量削峰策略
分层限流
@Configuration
public class FlowControlConfig {
@Bean
public RateLimiter rateLimiter() {
// 每秒100个请求
return RateLimiter.create(100);
}
@Component
public static class SeckillRateLimitFilter implements Filter {
@Autowired
private RateLimiter rateLimiter;
@Override
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain) throws IOException, ServletException {
if (!rateLimiter.tryAcquire()) {
HttpServletResponse resp = (HttpServletResponse) response;
resp.setStatus(503);
resp.setContentType("application/json");
resp.getWriter().write("{\"code\":503,\"message\":\"系统繁忙\"}");
return;
}
chain.doFilter(request, response);
}
}
}
请求排队
@Service
public class SeckillQueueService {
@Autowired
private RedissonClient redissonClient;
private static final String QUEUE_KEY = "seckill:queue";
// 排队请求
public Long enqueue(BigDecimal userId) {
RBlockingQueue<Long> queue = redissonClient.getBlockingQueue(QUEUE_KEY);
try {
queue.offer(userId, 5, TimeUnit.SECONDS);
return 1L;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return 0L;
}
}
}
面试核心考点总结
超卖问题解决方案
- Redis原子操作:使用
decr命令预扣库存 - 分布式锁:Redisson实现分布式锁
- 数据库乐观锁:
version字段防止并发更新 - MQ串行化:消息队列串行处理订单
高并发优化策略
- CDN加速:静态资源就近访问
- 缓存预热:提前加载热点数据
- 异步处理:消息队列削峰
- 熔断降级:保护核心服务
数据一致性保障
- 最终一致性:MQ异步处理订单
- 主动回滚:失败时补偿库存
- 定期核对:Redis与数据库库存核对
扩展性问题
- 水平扩展:Web服务无状态化
- Redis集群:主从+哨兵+Cluster
- MQ集群:高可用消息队列
实战建议
面试回答思路
第一层:功能实现(怎么做)
- 前端限流、按钮置灰
- Redis预扣库存、MQ异步下单
第二层:架构设计(怎么扩展)
- 分布式架构、集群部署
- 缓存、MQ、分库分表
第三层:性能优化(怎么优化)
- 并发压测、瓶颈分析
- JVM调优、SQL优化
第四层:可用性保障(怎么保障)
- 容灾备份、限流降级
- 监控告警、日志排查
常见面试问题
如何防止库存超卖?
2. 秒杀系统为什么用MQ?
3. Redis如何保证库存原子性?
4. 如何设计高可用的架构?
5. 系统如何横向扩展?
6. 如何保证数据最终一致性?
系统指标参考
并发量:设计支持10万+ QPS
响应时间:页面加载 < 200ms
下单延迟:< 2秒
成功率:> 99.9%
数据一致性:最终一致
这个设计案例涵盖了Java面试中的核心技术点,包括高并发处理、分布式系统设计、缓存优化、消息队列等,面试时能够清晰表达这些设计和实现思路,会给面试官留下深刻印象。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播