高并发系统设计:从理论到实践
——给零基础同学的第一课
大家好,我是团队的培训负责人,带过上百名应届生。每次看到新人面对“高并发”三个字就紧张,我就想起自己当初学的时候——连“并发”和“并行”都分不清,以为加个 synchronized 就万事大吉了。其实,高并发没那么神秘。今天这篇教程,就是为完全零基础的同学量身打造的,用最简单的语言、最真实的代码,带你从“听说”走向“会做”。
一、什么是高并发系统?它能做什么?
简单说:高并发系统就是能同时处理大量用户请求的系统。比如双11秒杀、春节抢票、热门直播——这些场景下,几万人甚至几百万人同时点击一个按钮,系统不能崩、不能慢、不能出错。
📌 关键目标:
- 可用性:系统不能宕机
- 响应快:用户点完别等太久
- 数据准:比如库存不能超卖
我们今天的目标,不是造出淘宝,而是亲手搭建一个能扛住一定压力的简易服务,理解背后的思路。
二、环境准备:5分钟搭好开发环境
你只需要安装以下工具(任选其一即可体验两种语言):
| 工具 | 用途 | 安装命令(Mac/Linux) |
|---|---|---|
| JDK 17+ | 运行 Spring Boot | sdk install java 17.0.12-tem |
| Maven 3.8+ | Java 项目构建 | brew install maven |
| Python 3.9+ | 运行 Flask 示例 | brew install python@3.9 |
| pip | Python 包管理 | 自带,无需额外安装 |
💡 提示:如果你是 Windows 用户,建议使用 WSL2 或直接下载官方安装包。
验证安装成功:
java -version # 应显示 17+
mvn -v # 显示 Maven 版本
python3 --version # 显示 3.9+
三、核心概念:用大白话讲清楚
1. 并发 vs 并行
- 并发(Concurrency):多个任务“交替执行”,看起来像同时进行(单核 CPU 也能做到)。
- 并行(Parallelism):多个任务“真正同时执行”(需要多核 CPU)。
我当初学的时候总混淆这两个词。记住:并发是逻辑上的同时, 并行是物理上的同时。
2. QPS(Queries Per Second)
每秒能处理多少请求。这是衡量系统性能的核心指标。比如你的接口 QPS=100,意味着最多支持 100 人/秒 同时访问。
3. 瓶颈在哪里?
高并发系统的瓶颈通常不在代码,而在:
- 数据库(磁盘 I/O 慢)
- 网络延迟
- 锁竞争(比如 synchronized 太粗暴)
四、实战项目:用 Spring Boot 和 Python 写一个计数器服务
我们要实现一个 /counter 接口,每次调用返回当前访问次数。看似简单,但在高并发下,这个数字很容易不准!
方案一:Spring Boot(Java)
步骤 1:创建项目
使用 start.spring.io 生成项目,选择:
- Language: Java
- Spring Boot: 3.x
- Dependencies: Spring Web
步骤 2:编写 Controller
@RestController
public class CounterController {
private volatile int count = 0;
@GetMapping("/counter")
public String counter() {
count++; // ⚠️ 危险!非原子操作
return "Count: " + count;
}
}
❌ 问题:
count++不是原子操作(读-改-写三步),多线程下会丢数据!
步骤 3:修复并发问题(使用 AtomicInteger)
import java.util.concurrent.atomic.AtomicInteger;
@RestController
public class SafeCounterController {
private AtomicInteger count = new AtomicInteger(0);
@GetMapping("/counter-safe")
public String counter() {
int current = count.incrementAndGet(); // 原子操作
return "Safe Count: " + current;
}
}
✅ 效果:即使 1000 个请求同时打进来,计数也准确。
方案二:Python(Flask + Redis)
Python 的 GIL(全局解释器锁)让多线程在 CPU 密集型任务中表现不佳,但我们可以通过 Redis 原子操作解决计数问题。
步骤 1:安装依赖
pip install flask redis
步骤 2:编写 app.py
from flask import Flask
import redis
app = Flask(__name__)
r = redis.Redis(host='localhost', port=6379, decode_responses=True)
@app.route('/counter')
def counter():
# 使用 Redis 的 INCR 命令,天然原子
count = r.incr('visit_count')
return f"Count: {count}"
if __name__ == '__main__':
app.run(threaded=True)
💡 为什么用 Redis?
因为 Redis 是单线程模型,所有命令天然串行执行,INCR操作绝对安全。
步骤 3:启动 Redis(Mac 示例)
brew install redis
redis-server
五、压测一下:看看你的系统能扛多少?
用 wrk 工具模拟高并发请求(安装:brew install wrk):
# 测试 Spring Boot 接口(假设运行在 8080 端口)
wrk -t12 -c400 -d30s http://localhost:8080/counter-safe
# 测试 Python 接口(假设运行在 5000 端口)
wrk -t12 -c400 -d30s http://localhost:5000/counter
参数说明:
-t12:12 个线程-c400:保持 400 个连接-d30s:持续 30 秒
你会看到输出中的 Requests/sec,这就是你的 QPS!
📊 典型结果对比(本地 MacBook Pro):
技术栈 QPS(估算) 优势 Spring Boot + AtomicInteger ~3000 JVM 优化成熟,内存管理强 Flask + Redis ~5000 Redis 性能极高,网络开销略大
六、新手常见问题解答(FAQ)
Q1:为什么不用数据库直接存 count?
A:数据库写入有磁盘 I/O,速度慢(毫秒级),而 Redis 在内存中(微秒级)。高并发下,数据库会成为瓶颈。
Q2:AtomicInteger 能无限增长吗?
A:不能!它最大值是 2^31-1。如果真要超高频计数,考虑用 分段计数 + 定期合并,或者直接上 Redis。
Q3:Python 的 GIL 会不会影响性能?
A:对于 I/O 密集型任务(如 Web 服务),GIL 影响不大,因为线程在等待网络/磁盘时会释放 GIL。我们的 Flask 例子正是如此。
Q4:Spring Boot 默认是单线程吗?
A:不是!Spring Boot 内嵌 Tomcat,默认会创建多个线程处理请求(可通过 server.tomcat.threads.max 配置)。
七、学习建议:下一步怎么走?
你已经迈出了高并发的第一步!接下来,我建议你按这个路径深入:
- 理解缓存:学习 Redis 的更多数据结构(如 Sorted Set 做排行榜)
- 消息队列:用 RabbitMQ/Kafka 解耦流量,削峰填谷
- 数据库优化:主从复制、分库分表(ShardingSphere)
- 限流熔断:用 Sentinel 或 Hystrix 防止雪崩
- 分布式锁:Redis 实现锁,解决跨服务并发问题
🔥 避坑指南:
- 不要一上来就学“分布式事务”,先搞定单机并发
- 不要迷信“微服务”,单体应用优化到位也能扛高并发
- 压测一定要做!没有数据支撑的优化都是玄学
结语
高并发不是魔法,而是一套可拆解、可练习、可验证的工程方法。我带过的很多应届生,都是从这样一个小小的计数器开始,一步步成长为能设计百万 QPS 系统的工程师。
记住:所有复杂的系统,都始于一行正确的代码。
现在,去跑通你的第一个高并发服务吧!遇到问题,欢迎留言讨论。

评论 0