分布式锁 - Redlock
Redlock
锁所需要具有的属性
- 独享 - 在任意一个时刻,只有一个客户端持有锁
- 无死锁 - 持锁客户端失联(崩溃、网络分区),锁仍然可以被自动释放
- 容错 - 只要大部分Redis节点都活着,客户端就可以获取和释放锁
面临的问题
- 系统层 - 网络分区、崩溃、重启等问题
- Redis层 - Redis节点的崩溃、重启等问题
- 客户端层 - 客户端的崩溃、重启等问题
- 重入 - 同一个客户端多次获取锁
- 锁续期 - 锁的有效期到了,但是业务还没有执行完,需要续期
- 释放 - 释放锁的时候,锁已经被其他客户端获取
- 时钟漂移 - 不同的Redis节点的时间不一致
- 时钟回拨 - 时钟回拨导致锁的有效期不准确
- 误删 - 误删其他客户端的锁
解决方法
- 互斥性 - 通过SETNX命令实现
- 无死锁 - 通过设置锁的过期时间实现
- 容错性 - 通过大多数原则实现
- 重入 - 通过客户端ID实现
- 锁续期 - 通过锁的过期时间实现
- 释放 - 通过客户端ID实现
- 时钟漂移 - 通过设置锁的过期时间实现
- 时钟回拨 - 通过设置锁的过期时间实现
- 误删 - 通过客户端ID实现
算法
单机算法
获取锁
SET resource_name my_random_value NX PX 30000
释放锁
1 |
|
分布式算法
- 获取锁
- 生成一个随机的客户端ID
- 依次向N个Redis节点获取锁
- 如果大多数Redis节点都获取到了锁,那么认为获取锁成功
- 如果获取锁失败,那么向所有Redis节点释放锁
Yii2 Redis lock 代码实现

- 随机数获取实现
Yii::$app->security->generateRandomString
底层依赖 https://www.php.net/manual/en/function.random-bytes.php
1 |
|
分布式锁 - Redlock
http://example.com/2024/11/27/redlock.html