分布式锁与限流
1. 这是什么
Redis 常被用于实现分布式锁和限流。 这类方案不是 Redis 的唯一用法,但在分布式系统里非常高频。
一句话理解:
- 分布式锁解决“跨节点互斥”
- 限流解决“超过容量时如何保护系统”
2. 为什么重要
很多跨节点互斥、幂等控制、请求保护场景,都会尝试借助 Redis 完成。 但如果不了解边界条件,很容易写出:
- 看起来可用
- 实际不安全
的方案。
3. 先建立直觉:锁和限流不是同一类问题
它们都可能用 Redis 实现,但解决的问题完全不同:
| 能力 | 主要问题 |
|---|---|
| 分布式锁 | 多个节点能不能同时进入临界区 |
| 限流 | 超过系统承载能力时,怎么限制入口流量 |
很多人会把所有并发问题都试图用锁解决,这是非常危险的。
4. 核心内容
4.1 分布式锁的基本模型
Redis 锁最常见的思路是:
- 用一个 key 表示锁是否被持有
- 用
SET key value NX PX ttl原子加锁
其中最关键的点有两个:
NX:只有 key 不存在时才设置PX ttl:避免锁永不释放
4.2 为什么释放锁一定要校验归属
这是 Redis 分布式锁最关键的安全点之一。 如果你只是简单:
text
DEL lock:key就有可能删掉别人加的锁。
所以正确思路通常是:
- 加锁时写入唯一 token
- 释放时先比对 token,再删除
4.3 锁超时与续期
锁必须设置过期时间,否则持锁节点挂掉时可能永远不释放。 但过期时间太短又可能导致:
- 业务还没执行完,锁先过期
这时就会涉及:
- 续期
- 看门狗机制
4.4 Redisson 认知
学习阶段不一定要立刻深挖所有实现细节,但要知道:
- Redisson 这类成熟客户端已经帮你处理了很多分布式锁细节
这也是为什么工程里往往更推荐:
- 用成熟实现
- 少手写不完整锁逻辑
4.5 限流的基本实现思路
Redis 限流常见思路包括:
- 固定窗口
- 滑动窗口
- 令牌桶 / 漏桶近似实现
核心目标都是:
- 在高峰流量来时保护系统容量
5. 学习重点
这一章最重要的是掌握:
- 分布式锁必须校验锁归属
- 锁超时和续期都是核心边界条件
- 锁不是万能方案,适用范围有限
- 限流本质是容量保护,而不是简单拒绝请求
6. 常见问题
6.1 释放锁时不校验归属
这是最危险的实现错误之一。
6.2 锁过期时间设置不合理
太短会误释放,太长会拖慢恢复。
6.3 把所有并发问题都试图用锁解决
很多问题其实更适合:
- 限流
- 幂等
- 队列削峰
7. 动手验证
这一节我已经在当前 Docker Redis 环境里实际验证过。
7.1 获取锁
bash
docker exec redis-lab redis-cli DEL lock:order
docker exec redis-lab redis-cli SET lock:order token-1 NX PX 30000
docker exec redis-lab redis-cli SET lock:order token-2 NX PX 30000我实际看到的关键结果是:
text
OK
(第二次获取失败,返回空结果)这说明:
- 第一次成功拿锁
- 第二次因为锁已存在而失败
7.2 安全释放锁
bash
docker exec redis-lab redis-cli EVAL "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end" 1 lock:order token-2
docker exec redis-lab redis-cli EVAL "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end" 1 lock:order token-1我实际验证到的结果是:
text
0
1这说明:
- 错误持有者不能释放锁
- 正确持有者才能删除锁
7.3 限流实验思路
如果你想进一步练习限流,可以从最简单的计数型窗口开始:
bash
docker exec redis-lab redis-cli INCR limit:api:user1
docker exec redis-lab redis-cli EXPIRE limit:api:user1 60你可以再结合应用层逻辑判断:
- 超过阈值就拒绝
8. 练习建议
- 写一个简单的 Redis 锁示例
- 设计一个秒杀接口限流策略
- 复盘 Redis 锁可能失效的边界情况
- 总结“锁适合什么问题,限流适合什么问题”
9. 自测问题
- 为什么分布式锁要绑定唯一标识?
- 锁续期是为了解决什么问题?
- 限流和加锁分别更适合哪类场景?
- 为什么说 Redis 锁“看起来简单,边界很多”?
10. 自测核对要点
- Redis 分布式锁的关键是原子加锁和安全释放
- 锁归属校验是必须条件
- 续期是为了避免业务未完成时锁提前失效
- 限流关注的是系统容量保护,不是互斥控制