Redis分布式锁争用与微服务并发粒度调优 - 第1节
1. 分布式锁基础:为什么需要分布式锁
1.1 从单体到分布式:锁的演进
在单体应用中,我们使用 synchronized 或 ReentrantLock 即可保证共享资源的互斥访问。但在微服务架构下,多个服务实例运行在不同的 JVM 进程甚至不同的物理节点上,传统的本地锁无法跨进程生效。
核心矛盾: 分布式环境下,多个节点需要像单机一样对共享资源进行互斥访问,但本地锁的作用域仅限于单个进程。
以下场景必须引入分布式锁:
- 库存扣减: 多个服务实例同时扣减同一商品库存,导致超卖。
- 定时任务调度: 集群中多个节点执行同一定时任务,只需一个节点执行。
- 幂等性控制: 防止重复支付、重复下单等操作。
- 资源隔离: 限制对数据库、文件系统等共享资源的并发访问。
1.2 分布式锁的核心要求
一个合格的分布式锁必须满足以下特性:
| 特性 | 说明 | 重要性 |
|---|---|---|
| 互斥性 | 任意时刻只有一个客户端持有锁 | 必须 |
| 死锁预防 | 持有锁的客户端崩溃后,锁能自动释放 | 必须 |
| 容错性 | 锁服务自身具备高可用,少数节点宕机不影响 | 高 |
| 可重入性 | 同一客户端可重复获取同一把锁 | 按需 |
| 公平性 | 按请求顺序分配锁(非必须) | 低 |
设计要点: 互斥性和死锁预防是分布式锁的底线要求。如果这两条无法保证,锁机制将失去意义。
2. 分布式锁的常见实现方式对比
2.1 基于数据库的实现
利用数据库的唯一索引或行锁实现互斥:
-- 加锁:插入一条唯一记录
INSERT INTO distributed_lock (lock_key, owner, expire_time)
VALUES ('order_123', 'instance_A', '2024-01-01 12:00:00');
-- 解锁:删除记录
DELETE FROM distributed_lock
WHERE lock_key = 'order_123' AND owner = 'instance_A';
优点: 实现简单,不依赖额外中间件。
缺点:
- 性能瓶颈:数据库 IO 开销大,高并发下容易成为热点。
- 死锁风险:客户端崩溃后记录无法自动清理,需额外兜底任务。
- 单点问题:数据库主从切换可能导致锁丢失。
2.2 基于 ZooKeeper 的实现
利用 ZooKeeper 的临时顺序节点和 Watcher 机制实现锁:
// 伪代码:ZooKeeper 分布式锁
1. 在 /locks/order_123 下创建临时顺序节点
2. 获取 /locks/order_123 下的所有子节点
3. 判断自己是否为最小序号节点
- 是:获得锁
- 否:监听前一个节点的删除事件,阻塞等待
优点:
- 强一致性:ZooKeeper 的 ZAB 协议保证数据一致性。
- 自动释放:临时节点在客户端断开后自动删除,避免死锁。
- 公平锁:顺序节点天然支持 FIFO 排队。
缺点:
- 性能较低:每次锁操作需多次网络往返和磁盘写入。
- 羊群效应:大量客户端同时监听同一节点时,惊群问题严重。
- 运维复杂:ZooKeeper 集群维护成本较高。
2.3 基于 Redis 的实现
利用 Redis 的 SET NX EX 原子命令实现锁:
// 加锁(原子操作)
SET lock_key unique_value NX EX 30
// 解锁(Lua 脚本保证原子性)
if redis.call("GET", KEYS[1]) == ARGV[1] then
return redis.call("DEL", KEYS[1])
else
return 0
end
优点:
- 高性能:纯内存操作,单机 QPS 可达 10 万+。
- 简单易用:API 简洁,学习成本低。
- 丰富的生态:Redisson、Jedis 等客户端提供成熟实现。
缺点:
- 一致性较弱:Redis 主从异步复制可能导致锁丢失。
- 需额外处理:锁超时、可重入、续期等逻辑需自行实现。
2.4 三种实现方式总结
| 对比维度 | 数据库 | ZooKeeper | Redis |
|---|---|---|---|
| 性能 | 低(磁盘 IO) | 中(ZAB 协议开销) | 高(纯内存) |
| 一致性 | 强(ACID) | 强(ZAB) | 弱(异步复制) |
| 死锁预防 | 需额外兜底 | 自动释放 | 超时自动释放 |
| 运维复杂度 | 低 | 高 | 低 |
| 适用场景 | 低并发、对一致性要求极高 | 对一致性要求极高、可接受较低吞吐 | 高并发、可接受弱一致性 |
选型建议: 在微服务架构中,Redis 分布式锁是主流选择。它兼顾了高性能和可接受的可靠性,配合 RedLock 算法或 Redisson 框架,可以满足绝大多数业务场景。ZooKeeper 更适合对一致性有强诉求的金融、交易类场景。数据库锁仅建议在低并发或作为兜底方案时使用。
2.5 为什么本课程选择 Redis
本课程后续章节将深入 Redis 分布式锁的实战调优,原因如下:
- 性能优势: Redis 单机 QPS 可达 10 万+,是 ZooKeeper 的 10 倍以上。
- 生态成熟: Redisson 提供了开箱即用的可重入锁、公平锁、读写锁、红锁等。
- 微服务亲和: Redis 作为缓存基础设施已广泛部署,引入分布式锁几乎零额外成本。
- 挑战性: Redis 的弱一致性带来了锁丢失、锁超时、锁续期等经典问题,正是调优的价值所在。