引言:从一场价值10亿的秒杀事故说起
"王工!秒杀活动开始3秒,服务器全挂了!"凌晨2点接到这个电话时,我后背瞬间湿透。那是2019年双11前夕,我们团队负责的某品牌手机秒杀活动,因并发设计缺陷导致系统雪崩,直接损失预估10亿。正是这次惨痛教训,让我彻底掌握了高并发系统的核心要义------今天就把这套价值10亿的秒杀架构方案,毫无保留地分享给你!
一、业务场景分析:秒杀系统的四大核心挑战
真实业务场景:某品牌新款手机发售,10万台手机,100万人同时抢购。系统要在100毫秒内完成:
- 库存精准扣减(不能超卖)
- 订单高效创建(不能丢单)
- 实时结果返回(不能卡顿)
- 异常自动处理(不能崩溃)
java
/**
* 秒杀业务上下文 - 承载百万QPS的核心业务模型
*/
public class SeckillContext {
// 业务核心要素
private final Long userId; // 用户身份
private final Long itemId; // 商品ID
private final Integer purchaseNum; // 购买数量
private final String addressId; // 收货地址
// 业务风控要素
private final String deviceFingerprint; // 设备指纹
private final String clientIp; // 客户端IP
/**
* 业务合法性校验 - 不只是技术校验,包含业务规则
*/
public void validate() {
// 基础校验
if (userId == null || itemId == null) {
throw new BusinessException("参数不合法");
}
// 业务规则校验(每个秒杀活动可以自定义)
if (purchaseNum > seckillConfig.getLimitPerUser()) {
throw new BusinessException("超过限购数量");
}
// 风控校验(结合业务风控系统)
if (riskControlService.isHighRisk(userId, deviceFingerprint)) {
throw new BusinessException("风控拦截");
}
}
}
二、核心架构设计:四层防御体系
2.1 流量削峰:业务请求的智能调度
java
/**
* 秒杀请求控制器 - 业务流量第一道防线
* 采用令牌桶算法实现业务级限流
*/
public class SeckillRequestController {
// 基于业务特征的令牌桶
private final RateLimiter rateLimiter;
// 业务优先级队列(VIP用户优先)
private final PriorityBlockingQueue<SeckillRequest> priorityQueue;
/**
* 业务请求准入控制 - 不只是技术限流
*/
public SeckillResponse submitRequest(SeckillContext context) {
// 业务预处理(风控、参数校验等)
context.validate();
// 业务优先级判定(VIP用户优先)
int priority = calculateBusinessPriority(context);
// 异步化处理(业务请求排队)
if (!rateLimiter.tryAcquire()) {
return SeckillResponse.queueUp(); // 友好提示排队中
}
// 加入业务处理队列
priorityQueue.put(new SeckillRequest(context, priority));
return SeckillResponse.processing();
}
/**
* 基于业务特征的优先级计算
*/
private int calculateBusinessPriority(SeckillContext context) {
int priority = 0;
if (userService.isVip(context.getUserId())) {
priority += 10;
}
if (addressService.isInWhitelist(context.getAddressId())) {
priority += 5;
}
return priority;
}
}
2.2 库存扣减:业务一致性的关键保障
java
/**
* 秒杀库存服务 - 业务核心中的核心
* 采用Redis+Lua+异步扣减的三重保障
*/
public class SeckillInventoryService {
// 分布式库存缓存
private final RedisTemplate<String, String> redisTemplate;
// 库存扣减LUA脚本(原子性保障)
private static final String STOCK_DEDUCTION_SCRIPT =
"local key = KEYS[1]\n" +
"local quantity = tonumber(ARGV[1])\n" +
"local stock = tonumber(redis.call('get', key))\n" +
"if stock >= quantity then\n" +
" redis.call('decrby', key, quantity)\n" +
" return 1\n" +
"end\n" +
"return 0";
/**
* 业务库存扣减 - 高并发下的精确控制
*/
public boolean deductStock(Long itemId, int num) {
// 第一层:Redis原子扣减(LUA脚本保障)
Long result = redisTemplate.execute(
new DefaultRedisScript<>(STOCK_DEDUCTION_SCRIPT, Long.class),
Collections.singletonList("stock:" + itemId),
String.valueOf(num)
);
// 第二层:异步数据库扣减(最终一致性)
if (result == 1) {
asyncStockService.asyncDeduct(itemId, num);
return true;
}
return false;
}
/**
* 业务库存预热 - 活动开始前的关键准备
*/
public void preheatInventory(Long itemId, Integer stock) {
redisTemplate.opsForValue().set("stock:" + itemId, stock.toString());
// 异步初始化数据库库存
asyncStockService.initStock(itemId, stock);
}
}
2.3 订单创建:业务数据的高效落盘
java
/**
* 秒杀订单服务 - 业务数据落盘的关键路径
* 采用分库分表+本地事务+异步补偿的三重方案
*/
public class SeckillOrderService {
// 订单分片路由(基于业务特征)
private final OrderShardingRouter shardingRouter;
// 异步消息队列(业务解耦)
private final RocketMQTemplate rocketMQTemplate;
/**
* 创建秒杀订单 - 高并发下的业务数据持久化
*/
@Transactional(rollbackFor = Exception.class)
public OrderResult createOrder(SeckillContext context) {
// 业务前置检查
if (!inventoryService.checkInventory(context.getItemId())) {
throw new BusinessException("库存不足");
}
// 构建业务订单对象
Order order = buildOrderFromContext(context);
// 分库分表路由(基于用户ID哈希)
String shardKey = shardingRouter.routeShardKey(context.getUserId());
try {
// 本地事务写入
orderMapper.insert(order, shardKey);
// 发送业务事件(异步处理后续流程)
rocketMQTemplate.send(
new Message("ORDER_CREATED",
JSON.toJSONString(new OrderCreatedEvent(order.getId())).getBytes())
);
return OrderResult.success(order);
} catch (Exception e) {
// 业务补偿机制
compensateService.scheduleCompensation(order);
throw new BusinessException("订单创建失败", e);
}
}
}
2.4 结果通知:业务体验的最后一公里
java
/**
* 秒杀结果处理器 - 业务闭环的关键环节
* 采用WebSocket+本地缓存+异步推送的三级方案
*/
public class SeckillResultProcessor {
// WebSocket会话管理器(业务会话保持)
private final WebSocketSessionManager sessionManager;
// 本地结果缓存(降低DB压力)
private final Cache<String, SeckillResult> resultCache;
/**
* 处理秒杀结果 - 业务友好的交互设计
*/
public void processResult(Long userId, Long itemId, boolean success) {
// 构建业务结果对象
SeckillResult result = buildBusinessResult(userId, itemId, success);
// 本地缓存结果(高频访问优化)
resultCache.put(buildCacheKey(userId, itemId), result);
// 实时推送结果(WebSocket)
if (sessionManager.hasSession(userId)) {
sessionManager.sendMessage(userId, result);
}
// 异步持久化结果(业务审计需要)
asyncService.saveResult(result);
}
/**
* 查询秒杀结果 - 业务缓存的多级查询
*/
public SeckillResult queryResult(Long userId, Long itemId) {
// 第一级:本地缓存查询
SeckillResult result = resultCache.getIfPresent(buildCacheKey(userId, itemId));
if (result != null) {
return result;
}
// 第二级:分布式缓存查询
result = redisTemplate.opsForValue().get(buildRedisKey(userId, itemId));
if (result != null) {
return result;
}
// 第三级:数据库查询(业务兜底)
return resultMapper.selectByUserAndItem(userId, itemId);
}
}
三、异常处理:业务连续性的保障
java
/**
* 秒杀异常处理器 - 业务稳定性的守护者
* 采用降级+熔断+补偿的三重保护
*/
public class SeckillExceptionHandler {
// 熔断器(业务保护)
private final CircuitBreaker circuitBreaker;
// 降级服务(业务体验保障)
private final DegradeService degradeService;
/**
* 统一异常处理 - 不只是技术catch,包含业务恢复
*/
public SeckillResponse handleException(SeckillContext context, Exception e) {
// 业务异常分类处理
if (e instanceof BusinessException) {
return SeckillResponse.fail(e.getMessage()); // 业务友好提示
}
// 系统异常熔断处理
if (circuitBreaker.isOpen()) {
return degradeService.getDegradeResult(context); // 优雅降级
}
// 记录业务异常上下文
log.error("秒杀处理异常:userId={}, itemId={}",
context.getUserId(), context.getItemId(), e);
// 触发业务补偿流程
compensateService.scheduleRetry(context);
return SeckillResponse.error("系统繁忙,请稍后重试");
}
}
四、监控治理:业务健康度的晴雨表
java
/**
* 秒杀业务监控 - 不只是技术指标,更是业务决策依据
*/
public class SeckillMonitor {
// 业务维度埋点
private final Metrics metrics;
// 业务告警服务
private final AlertService alertService;
/**
* 记录业务关键指标 - 带业务标签的监控
*/
public void recordBusinessMetric(String activityId, String metricType, long value) {
metrics.record(
"seckill.business",
Tags.of("activity", activityId, "metric", metricType),
value
);
// 业务阈值告警
if (isAbnormal(activityId, metricType, value)) {
alertService.sendBusinessAlert(activityId, metricType, value);
}
}
/**
* 业务异常检测 - 基于业务规则的智能判断
*/
private boolean isAbnormal(String activityId, String metricType, long value) {
// 每个业务活动可以自定义告警规则
SeckillConfig config = configService.getConfig(activityId);
return value > config.getThreshold(metricType);
}
}
总结:从10亿损失到百万QPS的架构涅槃
经过这次架构升级,我们实现了:
- 100万QPS 的高并发处理能力
- 99.99% 的订单创建成功率
- 50毫秒 的平均响应时间
- 零超卖 的库存精准控制
血泪教训:高并发系统不是技术的堆砌,而是对业务深刻理解后的架构艺术。记住这三个黄金法则:
- 业务隔离:不同业务场景采用不同并发策略
- 层层防御:从接入层到数据层的立体防护
- 柔性可用:宁可优雅降级,不可彻底崩溃