当系统只有 1 个人访问时,一切都很简单。
当 1000 个人同时访问时,系统才真正开始“考试”。
这一课,解决的就是:
- 并发下资源冲突
- 并发下系统被打爆
- 多实例环境的一致性问题
核心两件事:
- 分布式锁:保证“同一资源同一时刻只能一个人操作”
- 限流:保证“同一时刻来的人不要太多”
可以把它们理解为:
锁 = 唯一通行证
限流 = 门口安检
一、为什么需要这节课?
在单体应用中,你可能用synchronized就够了。
但在多台服务器场景下:
用户A → 服务器1 用户B → 服务器2两个服务器都认为自己是唯一的执行者 →数据错乱
典型问题:
- 秒杀超卖
- 定时任务重复执行
- 用户重复下单
- 报表重复生成
二、分布式锁:并发世界的“唯一钥匙”
1. 什么是分布式锁?
一句话:
在多台机器之间,保证同一时刻只有一个线程能进入临界区。
2. Redis 分布式锁核心语句
SET lock_key uuid NX PX 30000含义拆解
| 参数 | 含义 |
|---|---|
| SET | 设置键值 |
| NX | 不存在才设置 |
| PX 30000 | 30秒自动过期 |
| uuid | 锁持有者唯一标识 |
3. 为什么必须 PX?
防止死锁:
- 程序崩溃
- 锁没释放
- 所有人卡死
PX 相当于:
锁自动保险
4. 为什么要 UUID?
防止误删锁:
A拿锁 锁过期 B拿锁 A删除锁 → 把B的锁删了 ❌UUID 确保:
只能删除自己的锁
5. 最关键示例:A / B 争抢同一把锁(必须理解)
很多人到这里会有疑问:
锁不是会过期吗?
那过期之后会发生什么?
下面这个时间线,是理解分布式锁的核心。
场景设定
- 锁 TTL = 30 秒
- A 的业务执行时间 = 40 秒
- B 在第 31 秒来抢锁
- 锁 key =
lock:sku:1001 - A 的 uuid =
uuidA - B 的 uuid =
uuidB
时间线全过程
第 0 秒:A 加锁
SET lock:sku:1001 uuidA NX PX 30000Redis 中:
lock:sku:1001 = uuidAA 开始执行业务。
第 30 秒:锁过期(Redis 自动删除)
lock:sku:1001 不存在⚠️ 注意:
A 还在执行,但锁已经没了
第 31 秒:B 加锁
SET lock:sku:1001 uuidB NX PX 30000Redis 中:
lock:sku:1001 = uuidB此时出现一个重要事实:
A 和 B 同时在执行业务
第 40 秒:A 执行完成,尝试解锁
❌ 如果 A 直接执行:
DEL lock:sku:1001那么:
- 当前锁属于
uuidB - A 会把B 的锁删掉
- B 在“无锁状态下”继续执行 → 严重并发问题
✅ 正确解锁方式(UUID 校验)
如果当前 value == uuidA 才删除 否则 不删除此时 Redis 中是uuidB
与uuidA不相等 →不会删除
第 51 秒:B 执行完成,正常解锁
流程安全结束。
时间线总结表
| 时间 | Redis 锁状态 | A | B |
|---|---|---|---|
| 0s | uuidA | 执行中 | - |
| 30s | 不存在 | 执行中 | - |
| 31s | uuidB | 执行中 | 执行中 |
| 40s | uuidB | 结束 | 执行中 |
| 51s | 不存在 | - | 结束 |
这个例子说明了什么?
锁过期 ≠ 业务结束
过期后再加锁,是一把“新锁”
解锁必须校验 UUID
否则一定会误删别人的锁
6. 解锁必须用 Lua 脚本
因为 Redis 单线程,但命令不是事务。
必须做到:
- 比较 value
- 再删除
原子执行。
7. 分布式锁常见坑
| 坑 | 原因 | 解决 |
|---|---|---|
| 锁过期业务未完成 | TTL太短 | 续租/延长 |
| 锁误删 | 没UUID | UUID+Lua |
| 拿不到锁 | 高并发 | 重试/失败返回 |
三、限流:系统的流量闸门
1. 什么是限流?
限制单位时间内请求数量。
防止:
- 接口被打爆
- 数据库宕机
- 第三方服务雪崩
2. 常见限流算法
1)固定窗口
每分钟 100 次,分钟结束清零。
问题:边界抖动。
2)滑动窗口
更平滑,但复杂。
3)令牌桶(推荐)
思想:
- 按速率生成令牌
- 请求拿到令牌才放行
优点:
- 可突发
- 可控速
- 工程常用
3. 限流实现方式
单机限流
Guava RateLimiter
Resilience4j
分布式限流
Redis + Lua
网关限流(Nginx / Gateway)
四、锁 + 限流的真实组合
秒杀系统典型流程:
限流 → 防止冲垮系统 分布式锁 → 防止库存超卖 数据库唯一约束 → 最后兜底五、你要达到什么程度算掌握?
必会
- Redis 锁原理
- NX PX 含义
- UUID 作用
- 令牌桶思想
加分
- Lua 解锁
- 网关限流
- Redisson
六、面试标准回答
分布式锁常用 Redis 实现,通过 SET key value NX PX ttl 保证原子性与自动过期,value 使用 UUID 防止误删,解锁用 Lua 保证原子操作。
限流常用令牌桶算法,可在网关或服务层实现,用于削峰与保护下游系统。
七、一句话总结
分布式锁解决“抢同一资源”的问题,
限流解决“来太多人”的问题。
当你理解这一课,你的思维已经从“写接口”升级到“设计系统”。
下一篇:
第十六课实战:分布式锁与限流设计 —— 从原理到可跑 Demo