高并发系统设计:零基础也能动手做
大家好,我是你们的老朋友,一个从985毕业、在一线大厂摸爬滚打多年的全栈工程师。这几年我在掘金写了几十篇入门教程,经常收到私信:“高并发听起来好高级,我这种小白能学会吗?”
答案是:完全可以!
我当初学高并发的时候,也是一头雾水,以为必须懂分布式、微服务、Redis集群才能碰。但其实,高并发的核心思想非常朴素——用合理的结构处理大量用户同时访问。今天这篇教程,我会带你用 Java 写一个真实可运行的小项目,从零开始理解高并发。
一、什么是高并发?它和前端、Java、项目有什么关系?
简单说,高并发 = 很多人同时用你的系统。比如双十一抢购、春晚红包、热门新闻上线——成千上万人在一秒钟内点击同一个按钮。
- 前端:负责接收用户点击,发起请求(比如点击“下单”按钮)
- Java 后端:处理这些请求,比如扣库存、生成订单
- 项目:把这些功能整合起来,形成一个完整系统
如果你只写一个单机 Java 程序,1000 人同时请求,服务器很可能直接卡死。而高并发系统设计,就是教你怎么避免这种情况。
二、环境准备:5 分钟搭好开发环境
我们不需要复杂工具,只需以下三样:
| 工具 | 版本 | 用途 |
|---|---|---|
| JDK | 17+ | 运行 Java |
| Maven | 3.8+ | 管理依赖 |
| IntelliJ IDEA(或 VS Code) | 最新版 | 写代码 |
💡 新手提示:如果你还没装 JDK,去 Oracle 官网 或使用 OpenJDK。
创建一个新项目:
mkdir high-concurrency-demo
cd high-concurrency-demo
用 IDEA 打开,新建一个 Maven 项目,pom.xml 加入以下依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>3.2.0</version>
</dependency>
</dependencies>
📌 为什么用 Spring Boot?因为它简化了 Java Web 开发,几行代码就能启动 HTTP 服务。
三、核心概念:高并发的三大支柱
别被术语吓到,记住这三点就够了:
1. 限流(Rate Limiting)
防止系统被瞬间压垮。就像地铁限流,每分钟只放 100 人进站。
2. 缓存(Caching)
把常用数据存在内存里,避免每次查数据库。比如商品信息,查一次就存起来。
3. 异步(Asynchronous)
不重要的操作(如发邮件、记录日志)放到后台慢慢做,先快速响应用户。
四、实战项目:做一个“秒杀”模拟系统
我们将实现一个简化版秒杀功能:
- 商品库存 100
- 用户点击“抢购”
- 系统返回成功或失败
目标:支持 1000 个用户同时抢,不超卖!
步骤 1:写一个最简单的接口(无保护)
@RestController
public class SimpleSeckillController {
private int stock = 100;
@GetMapping("/seckill-simple")
public String seckill() {
if (stock > 0) {
stock--;
return "恭喜!抢到啦!剩余:" + stock;
}
return "没货了...";
}
}
问题在哪?
如果 10 个线程同时判断 stock > 0,都为 true,就会减 10 次——超卖!
步骤 2:加锁解决超卖(同步)
@GetMapping("/seckill-sync")
public synchronized String seckillSync() {
if (stock > 0) {
stock--;
return "抢到!剩余:" + stock;
}
return "没货了";
}
✅ 解决了超卖
❌ 但性能极差!所有请求排队执行,1000 人抢可能要等几分钟。
步骤 3:引入 Redis 缓存 + 原子操作
Redis 的 DECR 命令是原子的,天生线程安全!
先确保本地安装 Redis(Mac 用 brew install redis,Windows 用 WSL 或 Docker)。
启动 Redis:
redis-server
Java 代码:
@Autowired
private StringRedisTemplate redisTemplate;
@PostConstruct
public void initStock() {
redisTemplate.opsForValue().set("stock", "100");
}
@GetMapping("/seckill-redis")
public String seckillWithRedis() {
// 原子减 1
Long stock = redisTemplate.opsForValue().decrement("stock");
if (stock != null && stock >= 0) {
return "抢到!剩余:" + stock;
}
return "没货了";
}
✅ 高性能 ✅ 不超卖
步骤 4:加上限流(防刷)
用 Guava 的 RateLimiter 实现每秒最多 100 次请求:
// 全局限流器
private final RateLimiter limiter = RateLimiter.create(100.0); // 每秒100个令牌
@GetMapping("/seckill-limited")
public String seckillWithLimit() {
if (!limiter.tryAcquire()) {
return "请求太频繁,请稍后再试";
}
Long stock = redisTemplate.opsForValue().decrement("stock");
if (stock != null && stock >= 0) {
return "抢到!剩余:" + stock;
}
return "没货了";
}
现在,即使黑客用脚本疯狂刷,系统也不会崩。
五、新手常踩的坑 & 解决方案
❌ 坑 1:只在 Java 层加锁,忘了数据库也可能超卖
解决方案:数据库加唯一索引或用 SELECT ... FOR UPDATE,但性能差。推荐用 Redis 原子操作,如上所示。
❌ 坑 2:缓存雪崩(大量 key 同时过期)
解决方案:给缓存设置随机过期时间:
int expireTime = 300 + new Random().nextInt(60); // 5~6分钟
redisTemplate.expire("stock", expireTime, TimeUnit.SECONDS);
❌ 坑 3:前端没做防重复点击
解决方案:前端点击后禁用按钮,或加 loading 状态。例如 Vue 中:
<template>
<button @click="handleSeckill" :disabled="loading">
{{ loading ? '抢购中...' : '立即抢购' }}
</button>
</template>
<script>
export default {
data() {
return { loading: false }
},
methods: {
async handleSeckill() {
this.loading = true;
try {
await fetch('/seckill-limited');
} finally {
this.loading = false;
}
}
}
}
</script>
六、学习路径建议:下一步怎么走?
你现在已经掌握了高并发的最小可行知识。接下来可以:
- 深入 Redis:学习 Lua 脚本(保证多个操作原子性)、集群部署
- 了解消息队列:用 RabbitMQ/Kafka 实现真正的异步解耦
- 压测工具实践:用 JMeter 模拟 10000 并发,看系统表现
- 读经典案例:研究 12306、淘宝双 11 的架构演进
🌟 我的建议:不要一上来就学“分布式事务”“一致性哈希”。先用 Redis + 限流 + 异步解决 90% 的场景,再逐步深入。
结语:高并发不是魔法,而是工程思维
我见过太多初学者被“高并发”三个字吓退,其实它本质就是合理分配资源、避免瓶颈、快速响应。今天我们用不到 100 行 Java 代码,就实现了一个抗压的小系统。
记住:所有复杂的系统,都是从一行 System.out.println("Hello") 开始的。
如果你跟着做完这个项目,欢迎在评论区留言你的结果!遇到问题也可以问我——毕竟,我也是从“连 Redis 是啥都不知道”的小白过来的 😄
下期预告:《用 200 行代码搭建一个分布式任务调度系统》,敬请期待!

评论 0