软件开发分布式高并发进阶技能第五期精选排行榜TOP10
第十一部分与第十二部分将聚焦实战演练。理论铺垫之后,需要在真实场景中落地。秒杀是高并发系统中最具代表性的应用场景。
第十一部分:高并发实战案例 —— 秒杀系统架构设计
整合前述知识点,构建一个高并发秒杀系统。典型场景:100件库存商品,10万并发用户同时抢购。核心约束:禁止超卖、杜绝重复下单、保障系统不崩溃。
11.1 需求分析
库存有限,例如100件商品。
流量具有洪峰特性,10万用户在同一秒内涌入。
系统需确保三项核心底线:不超卖、不重复、不崩溃。
11.2 核心设计思路
核心策略:逐层削平流量峰值。
流量入口策略:
页面静态化并部署至CDN。
客户端请求采用随机延迟,避免同时涌向服务器。
API网关前置令牌桶限流,超速请求直接拦截。
库存管理关键措施:
秒杀前将库存预加载至Redis进行预热。
扣减库存必须使用Redis的`DECR`原子操作,扣减成功后才允许继续,否则立即拒绝。
请求处理异步化:
库存扣减成功后,避免直接创建数据库订单以防范锁死。将下单请求发送至消息队列,并返回“排队中,请稍候”。
后端消费者以串行或极低并发度处理消息并创建订单,有效降低数据库锁竞争。
防重复下单机制:
使用“用户ID+商品ID”作为唯一键约束,确保每个用户仅能参与一次秒杀。
降级方案:
当Redis或消息队列负载过高时,直接返回“活动火爆,请重试”,保障系统底线。
11.3 伪代码实现
@RestController
public class SeckillController {
@Autowired
private RedisTemplate redis;
@Autowired
private RocketMQTemplate mq;
@PostMapping("/seckill")
public String seckill(Long userId, Long productId) {
// 1. 限流(使用 Sentinel)
// 2. 校验是否已秒杀过(Redis Set)
Boolean already = redis.opsForSet().isMember("seckill:user:" + productId, userId);
if (Boolean.TRUE.equals(already)) {
return "您已参与过该活动";
}
// 3. 原子扣减库存
Long stock = redis.opsForValue().decrement("seckill:stock:" + productId);
if (stock == null || stock < 0) {
// 库存不足,恢复库存(decrement 后为负,需加回)
redis.opsForValue().increment("seckill:stock:" + productId);
return "已抢光";
}
// 4. 记录用户参与(避免重复扣减)
redis.opsForSet().add("seckill:user:" + productId, userId);
// 5. 发送消息异步创建订单
SeckillOrderMsg msg = new SeckillOrderMsg(userId, productId);
mq.syncSend("seckill_order_topic", msg);
return "排队中,请稍后查询结果";
}
}
@RocketMQMessageListener(topic = "seckill_order_topic", consumerGroup = "order-group")
public class OrderConsumer implements RocketMQListener {
@Autowired
private OrderService orderService;
@Override
public void onMessage(SeckillOrderMsg msg) {
// 幂等:使用唯一键约束(userId + productId)
orderService.createSeckillOrder(msg.getUserId(), msg.getProductId());
}
}
11.4 数据库表设计
CREATE TABLE `seckill_order` (
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint NOT NULL,
`product_id` bigint NOT NULL,
`status` tinyint DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_user_product` (`user_id`,`product_id`) -- 防重
);
系统设计与上线完成。然而分布式系统中,故障是常态而非例外。最后一部分讨论如何快速定位故障根因。
第十二部分:高并发系统的可观测性 —— 指标、链路、日志
分布式系统故障如同黑箱排查,需要借助可观测性三大支柱:指标(Metrics)、分布式链路追踪(Tracing)、日志(Logging)。
12.1 指标监控(Prometheus + Grafana)
每个微服务暴露`/metrics`端点,由Prometheus定期拉取并存储为时序数据,最终通过Grafana可视化展示。
核心监控指标包括:QPS、延迟(尤其关注P99)、错误率、CPU/内存/GC状况、线程池活跃数、消息队列积压量。这些指标直接反映系统健康状况。
12.2 分布式链路追踪(SkyWalking、Jaeger)
请求在微服务间流转时,需明确其经过的服务路径、各步骤耗时及失败位置。链路追踪通过为每个请求分配全局唯一的Trace ID,并记录每个Span来实现。
集成Spring Cloud Sleuth配置示例:
spring:
zipkin:
base-url: http://zipkin:9411
sleuth:
sampler:
probability: 1.0 # 采样率
配置完成后,日志自动注入Trace ID。排查问题时,搜索该ID即可串联出请求的完整路径,显著提升定位效率。
12.3 日志收集(ELK Stack)
日志是问题分析的最终素材。采用Filebeat采集日志,Logstash进行过滤,Elasticsearch负责存储与搜索,Kibana提供可视化界面。
告警机制可基于Prometheus Alertmanager或Kibana Watcher。当错误率突增或队列积压超过阈值,自动触发钉钉或邮件通知,确保值班人员及时响应。
