高并发系统设计:从理论到实践(初学者友好教程)
开篇:什么是高并发系统?我们为什么需要它?

在互联网应用中,有些场景下会突然涌入大量用户请求。比如:
- 双十一的电商抢购
- 新年发红包
- 抢演唱会门票
这类场景的共同点是:短时间处理大量请求。普通的程序在这种情况下会出现卡顿、崩溃、数据出错等问题。
这就是我们需要“高并发系统设计”的原因:让我们的系统在面对成千上万并发请求时依然能稳定运行。
本教程将带你一步步了解这个概念,并通过一个简单的项目,动手实现一个基础但具备高并发能力的小服务。
环境准备:搭建开发环境

所需工具清单:
- 操作系统:Windows / macOS / Linux 均可
- 编程语言:Python 3.6+
- Web 框架:Flask 或 FastAPI
- 数据库:SQLite(轻量级本地数据库)
- 并发测试工具:Postman + JMeter / Locust
- 代码编辑器:VSCode 或 PyCharm
安装步骤(以 Python + Flask 为例):
安装 Python
- Windows: 从 https://www.python.org/downloads/ 下载安装
- macOS:
brew install python - Linux:
sudo apt install python3
安装 Flask 框架
pip install flask安装 SQLite 浏览器(可选)
推荐使用 DB Browser for SQLite(免费开源)
下载地址:https://sqlitebrowser.org/安装并发测试工具 Locust
pip install locust
安装完成后,你可以用以下命令验证是否成功:
python --version
flask --version
locust --version
核心概念:理解高并发的几个关键词

高并发系统设计中,有几组关键术语你必须熟悉,我们用简单语言解释一下:
1. 并发与并行
- 并发(Concurrency):多个任务交替执行,看起来像是同时进行(例如一个人做饭时切菜和烧水交替做)
- 并行(Parallelism):多个任务真正的同时执行(例如多个人一起做饭)
在单核 CPU 上只能做到并发,在多核 CPU 上可以做到并行。
2. 吞吐量(Throughput)
单位时间内能处理多少个请求。比如每秒能处理 1000 个请求,那么吞吐量就是 1000 req/s。
📌 小技巧:吞吐量越高越好,但不能超过服务器性能上限
3. 请求队列(Request Queue)
如果请求太多,来不及处理,这些请求会被放到一个队列里排队等候,这就是请求队列。就像银行窗口前面排的队。
4. 线程 vs 进程
| 类型 | 特点 | 使用场景 |
|---|---|---|
| 线程 | 轻量、共享内存、切换开销小 | 适合 I/O 密集型任务(如网络请求、文件读写) |
| 进程 | 独立、资源多、切换开销大 | 适合计算密集型任务(如图像处理、复杂运算) |
⚠️ 初学者建议先掌握线程使用
5. 异步(Asynchronous)
异步编程是指某些操作可以在不阻塞主程序的前提下执行。例如下载文件时不需要等它完成,就可以继续响应其他请求。
实战项目:打造一个支持高并发的抽奖接口

我们将构建一个简单的抽奖系统,并逐步提升它的并发能力。
第一步:创建基本接口
新建文件 app.py,内容如下:
from flask import Flask, jsonify
import sqlite3
app = Flask(__name__)
def init_db():
conn = sqlite3.connect('lottery.db')
cursor = conn.cursor()
cursor.execute('''CREATE TABLE IF NOT EXISTS prizes (
id INTEGER PRIMARY KEY,
name TEXT,
stock INTEGER)''')
# 初始化奖品库存
cursor.execute("INSERT OR IGNORE INTO prizes (id, name, stock) VALUES (1, 'iPhone', 10)")
conn.commit()
conn.close()
@app.route('/draw', methods=['GET'])
def draw_prize():
conn = sqlite3.connect('lottery.db')
cursor = conn.cursor()
# 查询当前奖品库存
cursor.execute("SELECT stock FROM prizes WHERE id=1")
stock = cursor.fetchone()[0]
if stock <= 0:
return jsonify({"error": "没有库存了"}), 400
# 减少库存
cursor.execute("UPDATE prizes SET stock = stock - 1 WHERE id = 1")
conn.commit()
conn.close()
return jsonify({"message": "恭喜获得奖品!", "remaining_stock": stock - 1})
if __name__ == '__main__':
init_db()
app.run(debug=True)
启动服务:
python app.py
访问 http://localhost:5000/draw,你会看到库存递减。
第二步:模拟并发请求(发现并发问题)
用 Locust 来测试并发情况。
新建文件 locustfile.py:
from locust import HttpUser, task
class LotteryUser(HttpUser):
@task
def draw_prize(self):
self.client.get("/draw")
启动 Locust:
locust -f locustfile.py
然后打开浏览器进入 Locust 控制台: http://localhost:8089
设置用户数为 1000,每秒启动 100 用户进行压测。
⚠️ 你会发现库存可能变成负数!这就是典型的并发安全问题。
第三步:加锁解决并发问题
修改代码,加上线程锁:
from flask import Flask, jsonify
import sqlite3
import threading
app = Flask(__name__)
lock = threading.Lock() # 创建锁对象
@app.route('/draw', methods=['GET'])
def draw_prize():
with lock: # 加锁开始
conn = sqlite3.connect('lottery.db')
cursor = conn.cursor()
cursor.execute("SELECT stock FROM prizes WHERE id=1")
stock = cursor.fetchone()[0]
if stock <= 0:
return jsonify({"error": "没有库存了"}), 400
cursor.execute("UPDATE prizes SET stock = stock - 1 WHERE id = 1")
conn.commit()
conn.close()
return jsonify({"message": "恭喜获得奖品!", "remaining_stock": stock - 1})
再次用 Locust 测试,你会发现库存不再出现负值了。
🎉 成功解决了并发安全问题!
常见问题解答(FAQ)
Q1:为什么要加锁?不加有什么后果?
A:因为多个线程可能同时读取并更新同一个数据,导致数据不一致。比如两个线程同时读到库存为1,都以为还能抽一次,结果减成 -1。
加锁保证同一时刻只有一个线程处理这个逻辑,确保数据一致性。
Q2:Python 的 GIL 是什么?会影响并发性能吗?
A:GIL(全局解释器锁)是 Python 解释器中的一个机制,限制了同时只有一个线程执行 Python 字节码。这意味着在 CPU 计算密集型任务中,多线程无法发挥多核优势。
但在 I/O 密集型任务(如网络请求、数据库操作)中,影响不大,仍可利用多线程提高效率。
Q3:除了加锁,还有别的方法避免并发问题吗?
A:有的,常见方法包括:
- 使用数据库事务 + 行锁(推荐用于生产环境)
- 使用原子性数据库语句(如
UPDATE ... WHERE) - 使用队列系统(如 Redis + Lua脚本控制)
- 使用无状态设计 + 分布式缓存
学习建议:下一步学什么?
当你已经掌握了基本的并发问题处理之后,可以尝试学习以下方向:
🧱 构建更专业的高并发架构
| 主题 | 简要说明 |
|---|---|
| Redis 缓存 | 提升热点数据访问速度,减少数据库压力 |
| 数据库分表 | 分担单表压力,提升性能 |
| 限流与降级 | 防止突发流量击垮服务 |
| 异步队列(RabbitMQ/Kafka) | 解耦业务流程,提升并发承载力 |
| 负载均衡(Nginx) | 多实例部署,提高可用性 |
| 微服务拆分 | 模块化复杂系统,便于扩展维护 |
📘 推荐阅读书目
- 《高性能 MySQL》
- 《Redis 设计与实现》
- 《Java并发编程实战》
- 《微服务架构设计模式》
🔍 学习路径图建议:
并发基础 → 数据库优化 → 异步与消息队列 → 分布式架构 → 性能调优与监控
结尾语:动手才是硬道理!
高并发系统设计并不是一蹴而就的能力,而是随着实践经验不断积累的结果。你已经完成了第一个高并发接口的设计和测试,接下来要做的是:
✅ 在自己的项目中反复练习
✅ 给接口加日志、限流等功能
✅ 尝试用 Redis 替换 SQLite 实现库存管理
✅ 对接 Nginx 做负载均衡
只要你坚持实践、持续提问、不断总结,很快就能成为懂系统的后端工程师!
✅ 教程源码已上传至 GitHub:https://github.com/example/high-concurrency-demo
💬 如有疑问欢迎留言交流,我们共同进步!

评论 0