高并发系统如何设计?
高并发系统设计是后端开发的核心技能之一。下面将从架构、技术、实践等多个维度,系统地讲解高并发系统的设计方法。
一、高并发的核心挑战
1. 什么是高并发?
高并发是指在同一时刻有大量用户同时访问系统,系统需要处理大量的请求。常见的高并发场景:
- 电商秒杀:双11、618等大促活动
- 社交应用:微博热搜、朋友圈点赞
- 直播平台:百万用户同时在线观看
- 金融交易:股票交易系统
2. 高并发带来的问题
| 问题类型 | 具体表现 | 影响 |
|---|---|---|
| 性能问题 | 响应时间变长、吞吐量下降 | 用户体验差 |
| 资源问题 | CPU、内存、网络资源耗尽 | 系统崩溃 |
| 数据问题 | 数据不一致、脏读、幻读 | 业务错误 |
| 稳定性问题 | 服务雪崩、级联故障 | 系统不可用 |
二、高并发系统设计原则
1. 分层设计原则
┌─────────────────────────────────────┐
│ 接入层(CDN + 负载均衡) │
├─────────────────────────────────────┤
│ 网关层(限流 + 认证) │
├─────────────────────────────────────┤
│ 应用层(业务逻辑) │
├─────────────────────────────────────┤
│ 服务层(微服务) │
├─────────────────────────────────────┤
│ 数据层(缓存 + 数据库) │
├─────────────────────────────────────┤
│ 存储层(文件 + 对象存储) │
└─────────────────────────────────────┘
2. 核心设计原则
(1)无状态设计
- 应用服务器不保存会话状态
- 会话信息存储在 Redis 等外部存储
- 便于水平扩展
(2)水平扩展
- 通过增加服务器数量提升处理能力
- 使用负载均衡分发请求
- 避免单点故障
(3)读写分离
- 读多写少的场景,分离读写操作
- 主库负责写,从库负责读
- 提升数据库吞吐量
(4)缓存优先
- 热点数据放入缓存
- 减少数据库访问
- 提升响应速度
(5)异步处理
- 非核心流程异步化
- 使用消息队列削峰填谷
- 提升系统吞吐量
三、高并发核心技术
1. 负载均衡
负载均衡算法
| 算法 | 原理 | 适用场景 |
|---|---|---|
| 轮询(Round Robin) | 按顺序轮流分配 | 服务器性能相近 |
| 加权轮询 | 根据权重分配 | 服务器性能不同 |
| 最少连接 | 分配给当前连接最少的服务器 | 长连接场景 |
| IP Hash | 根据客户端IP计算Hash | 需要会话保持 |
| 一致性Hash | 带虚拟节点的Hash算法 | 缓存场景 |
实现方案
// Nginx 配置示例
upstream backend {
server 192.168.1.1:8080 weight=5;
server 192.168.1.2:8080 weight=5;
server 192.168.1.3:8080 backup;
# 一致性Hash
hash $request_uri consistent;
}
server {
listen 80;
location / {
proxy_pass http://backend;
}
}
2. 缓存策略
多级缓存架构
┌─────────────┐
│ 浏览器缓存 │ ← 缓存静态资源
├─────────────┤
│ CDN缓存 │ ← 缓存热点资源
├─────────────┤
│ 应用缓存 │ ← 本地缓存(Caffeine)
├─────────────┤
│ 分布式缓存 │ ← Redis集群
├─────────────┤
│ 数据库 │ ← 持久化存储
└─────────────┘
缓存更新策略
| 策略 | 优点 | 缺点 |
|---|---|---|
| Cache Aside | 简单、灵活 | 可能不一致 |
| Read/Write Through | 一致性高 | 实现复杂 |
| Write Behind | 性能高 | 可能丢数据 |
缓存问题及解决方案
缓存穿透
- 问题:查询不存在的数据,每次都打到数据库
- 解决:布隆过滤器、缓存空值
缓存击穿
- 问题:热点key过期,大量请求打到数据库
- 解决:互斥锁、逻辑过期
缓存雪崩
- 问题:大量key同时过期,数据库压力剧增
- 解决:随机过期时间、多级缓存
3. 数据库优化
读写分离
@Configuration
public class DataSourceConfig {
@Bean
public DataSource routingDataSource() {
DynamicRoutingDataSource routingDataSource = new DynamicRoutingDataSource();
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put("master", masterDataSource());
targetDataSources.put("slave", slaveDataSource());
routingDataSource.setTargetDataSources(targetDataSources);
routingDataSource.setDefaultTargetDataSource(masterDataSource());
return routingDataSource;
}
}
分库分表
垂直拆分:按业务拆分
用户库:user_db
订单库:order_db
商品库:product_db
水平拆分:按数据量拆分
order_db_0: order_0, order_1, order_2
order_db_1: order_3, order_4, order_5
索引优化
-- 创建复合索引
CREATE INDEX idx_order_user_time ON orders(user_id, create_time);
-- 覆盖索引
CREATE INDEX idx_order_cover ON orders(user_id, status, total_amount);
4. 消息队列
消息队列的作用
- 异步处理:提升响应速度
- 流量削峰:平滑处理突发流量
- 应用解耦:降低系统耦合度
- 数据分发:一对多消息分发
消息队列选型
| 特性 | Kafka | RabbitMQ | RocketMQ |
|---|---|---|---|
| 吞吐量 | 百万级 | 万级 | 十万级 |
| 延迟 | 毫秒级 | 微秒级 | 毫秒级 |
| 可靠性 | 高 | 高 | 非常高 |
| 适用场景 | 日志、大数据 | 企业应用 | 金融交易 |
消息可靠性保证
@Service
public class OrderService {
@Autowired
private RocketMQTemplate rocketMQTemplate;
public void createOrder(Order order) {
// 1. 保存订单到数据库
orderMapper.insert(order);
// 2. 发送消息(异步)
SendResult sendResult = rocketMQTemplate.syncSend(
"order-topic",
MessageBuilder.withPayload(order).build()
);
// 3. 确认消息发送成功
if (!sendResult.getSendStatus().equals(SendStatus.SEND_OK)) {
// 处理发送失败
}
}
}
5. 限流降级
限流算法
| 算法 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| 计数器 | 固定时间窗口计数 | 简单 | 突发流量问题 |
| 滑动窗口 | 滑动时间窗口计数 | 平滑 | 实现复杂 |
| 漏桶 | 请求放入桶中,匀速处理 | 平滑 | 不能应对突发 |
| 令牌桶 | 匀速产生令牌,请求消耗令牌 | 灵活 | 实现复杂 |
限流实现
@Component
public class RateLimiterFilter extends OncePerRequestFilter {
private final RateLimiter rateLimiter = RateLimiter.create(1000); // 每秒1000个请求
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
if (rateLimiter.tryAcquire()) {
filterChain.doFilter(request, response);
} else {
response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
response.getWriter().write("请求过于频繁,请稍后再试");
}
}
}
降级策略
@Component
public class OrderServiceFallback implements OrderService {
@Override
@SentinelResource(value = "createOrder", fallback = "createOrderFallback")
public Order createOrder(OrderRequest request) {
// 正常业务逻辑
}
public Order createOrderFallback(OrderRequest request, Throwable ex) {
// 降级逻辑:返回默认值或缓存数据
log.warn("创建订单降级,原因:{}", ex.getMessage());
return Order.builder()
.status(OrderStatus.PENDING)
.message("系统繁忙,请稍后查询订单状态")
.build();
}
}
四、高并发架构模式
1. 微服务架构
┌─────────────────────────────────────────┐
│ API Gateway │
│ (限流、认证、路由) │
└─────────────────────────────────────────┘
│
┌───────────────┼───────────────┐
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ 用户服务 │ │ 订单服务 │ │ 商品服务 │
└─────────┘ └─────────┘ └─────────┘
│ │ │
└───────────────┼───────────────┘
▼
┌─────────────┐
│ 服务注册中心 │
│ (Nacos) │
└─────────────┘
2. CQRS 模式(命令查询职责分离)
┌─────────────┐ ┌─────────────┐
│ 写操作 │ ──────> │ 写数据库 │
│ Command │ │ (主库) │
└─────────────┘ └─────────────┘
│
▼
┌─────────────┐
│ 事件总线 │
│ (MQ) │
└─────────────┘
│
▼
┌─────────────┐ ┌─────────────┐
│ 读操作 │ <────── │ 读数据库 │
│ Query │ │ (从库) │
└─────────────┘ └─────────────┘
3. 事件驱动架构
┌─────────┐ 创建订单 ┌─────────┐
│ 用户 │ ────────────> │ 订单服务 │
└─────────┘ └────┬────┘
│
┌──────────┼──────────┐
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│库存服务 │ │支付服务 │ │物流服务 │
└─────────┘ └─────────┘ └─────────┘
五、高并发实践案例
案例1:电商秒杀系统
核心挑战
- 瞬时流量巨大(百万级并发)
- 库存超卖问题
- 系统稳定性要求高
解决方案
┌─────────────┐
│ CDN加速 │ ← 静态资源缓存
├─────────────┤
│ 秒杀网关 │ ← 限流、鉴权
├─────────────┤
│ 库存预扣 │ ← Redis原子操作
├─────────────┤
│ 异步下单 │ ← MQ削峰
├─────────────┤
│ 订单处理 │ ← 数据库最终一致
└─────────────┘
关键代码
@Service
public class SeckillService {
@Autowired
private StringRedisTemplate redisTemplate;
@Autowired
private RedissonClient redissonClient;
@Autowired
private RocketMQTemplate rocketMQTemplate;
/**
* 秒杀下单
*/
public SeckillResult seckill(Long userId, Long productId) {
// 1. 用户限流检查
if (!checkUserLimit(userId)) {
return SeckillResult.fail("操作过于频繁");
}
// 2. 获取分布式锁
RLock lock = redissonClient.getLock("seckill:product:" + productId);
try {
if (!lock.tryLock(3, 10, TimeUnit.SECONDS)) {
return SeckillResult.fail("系统繁忙,请重试");
}
// 3. Redis预扣库存(Lua脚本保证原子性)
Long stock = redisTemplate.execute(
new DefaultRedisScript<>(SECKILL_SCRIPT, Long.class),
Collections.singletonList("stock:" + productId),
userId.toString()
);
if (stock == null || stock < 0) {
return SeckillResult.fail("库存不足");
}
// 4. 发送异步下单消息
SeckillOrderMessage message = SeckillOrderMessage.builder()
.userId(userId)
.productId(productId)
.build();
rocketMQTemplate.asyncSend("seckill-order-topic", message, new SendCallback() {
@Override
public void onSuccess(SendResult sendResult) {
log.info("秒杀订单消息发送成功");
}
@Override
public void onException(Throwable e) {
// 消息发送失败,回滚库存
redisTemplate.opsForValue().increment("stock:" + productId);
}
});
return SeckillResult.success("抢购成功,正在处理订单");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return SeckillResult.fail("系统异常");
} finally {
lock.unlock();
}
}
// Lua脚本:原子性扣减库存
private static final String SECKILL_SCRIPT =
"if (redis.call('exists', KEYS[1]) == 1) then " +
" local stock = tonumber(redis.call('get', KEYS[1])); " +
" if (stock > 0) then " +
" redis.call('decr', KEYS[1]); " +
" return stock - 1; " +
" end; " +
" return -1; " +
"end; " +
"return -1;";
}
案例2:社交应用Feed流
核心挑战
- 海量数据(亿级)
- 实时性要求高
- 个性化推荐
解决方案
推拉结合模式
┌─────────────────────────────────────────┐
│ 写扩散(Push) │
│ 大V发布内容 → 推送给所有粉丝 │
├─────────────────────────────────────────┤
│ 读扩散(Pull) │
│ 普通用户发布 → 粉丝拉取时间线 │
└─────────────────────────────────────────┘
多级缓存
┌─────────────┐
│ L1: 本地缓存 │ ← 用户最近Feed
├─────────────┤
│ L2: Redis │ ← 热点Feed
├─────────────┤
│ L3: HBase │ ← 全量Feed
└─────────────┘
六、高并发监控与运维
1. 监控指标
| 指标类型 | 具体指标 | 告警阈值 |
|---|---|---|
| 系统指标 | CPU、内存、磁盘、网络 | CPU > 80% |
| 应用指标 | QPS、RT、错误率 | 错误率 > 1% |
| 业务指标 | 订单量、支付成功率 | 成功率 < 95% |
| 中间件指标 | Redis、MQ、DB性能 | 连接数 > 80% |
2. 压测方案
# JMeter压测命令
jmeter -n -t seckill_test.jmx -l result.jtl -e -o report
# 关键指标
- 吞吐量(Throughput)
- 响应时间(Response Time)
- 错误率(Error Rate)
- 并发用户数(Concurrent Users)
七、总结
高并发系统设计需要从多个维度进行考虑:
1. 架构层面
- 分层设计,职责清晰
- 无状态设计,便于扩展
- 微服务架构,独立部署
2. 技术层面
- 负载均衡,流量分发
- 多级缓存,减少数据库压力
- 读写分离,提升数据库性能
- 消息队列,异步削峰
- 限流降级,保证系统稳定
3. 数据层面
- 分库分表,水平扩展
- 索引优化,提升查询性能
- 最终一致性,保证数据正确
4. 运维层面
- 全链路监控,及时发现问题
- 自动化运维,提升效率
- 容量规划,提前扩容
高并发系统设计是一个持续优化的过程,需要根据业务特点和实际场景,选择合适的技术方案,并在实践中不断调整和优化。
互动话题
- 你在实际项目中遇到过哪些高并发挑战?是如何解决的?
- 对于秒杀系统,你还有什么其他的优化方案?
- 在微服务架构中,你是如何处理分布式事务的?
欢迎在评论区交流讨论!
欢迎关注公众号:服务端技术精选,获取更多技术分享和经验。
标题:高并发系统如何设计?
作者:jiangyi
地址:http://www.jiangyi.space/articles/2026/03/18/1773586027363.html
公众号:服务端技术精选
- 一、高并发的核心挑战
- 1. 什么是高并发?
- 2. 高并发带来的问题
- 二、高并发系统设计原则
- 1. 分层设计原则
- 2. 核心设计原则
- (1)无状态设计
- (2)水平扩展
- (3)读写分离
- (4)缓存优先
- (5)异步处理
- 三、高并发核心技术
- 1. 负载均衡
- 负载均衡算法
- 实现方案
- 2. 缓存策略
- 多级缓存架构
- 缓存更新策略
- 缓存问题及解决方案
- 3. 数据库优化
- 读写分离
- 分库分表
- 索引优化
- 4. 消息队列
- 消息队列的作用
- 消息队列选型
- 消息可靠性保证
- 5. 限流降级
- 限流算法
- 限流实现
- 降级策略
- 四、高并发架构模式
- 1. 微服务架构
- 2. CQRS 模式(命令查询职责分离)
- 3. 事件驱动架构
- 五、高并发实践案例
- 案例1:电商秒杀系统
- 核心挑战
- 解决方案
- 关键代码
- 案例2:社交应用Feed流
- 核心挑战
- 解决方案
- 六、高并发监控与运维
- 1. 监控指标
- 2. 压测方案
- 七、总结
- 1. 架构层面
- 2. 技术层面
- 3. 数据层面
- 4. 运维层面
- 互动话题
评论
0 评论