Skip to content

redis分布式锁问题

推荐方案:SET EX PX NX + 校验唯一随机值【线程id】, 再释放锁。

java
String keyResourceId = "your_key_here";
String uniRequestId = "your_unique_request_id_here";
int expireTimeInSeconds = 100;

String result = jedis.set(keyResourceId, uniRequestId, "NX", "EX", expireTimeInSeconds);

if ("OK".equals(result)) { // 如果设置成功,获取到了锁
    try {
        // 做业务处理
        // do something
    } catch (Exception e) {
        // 处理异常
    } finally {
        // 获取当前锁的值,如果是当前线程设置的锁,则释放锁
        String currentValue = jedis.get(keyResourceId);
        if (uniRequestId.equals(currentValue)) {
            jedis.del(keyResourceId); // 释放锁
        }
    }
}

redis分布式锁致命4问

看看你设计的redis锁能经得住几问

1.锁过期释放,业务未执行完

解决方案:设置锁续约机制,假设线程A获取了锁开始执行业务,我们可以开启一个守护线程,守护线程每过一段时间就检测线程A的执行情况,如果A为执行完,我们就给锁做一个续约操作。

PS:Redisson中实现了看门狗机制。

2.锁被其它线程释放

通过校验唯一值解决,上述方案已解决。

3.加锁和释放锁都不是原子操作,问题应该如何解决

加锁和释放锁的所有业务一起执行

4.主master节点挂机,导致主从节点同时对一个key加锁

场景:生产环境下,我们使用redis主从+哨兵模式,主节点对一个key加锁后挂掉了,然后新的主节点产生,但之前并没有同步到锁,导致又加了一次锁,重复加锁。

解决方案:

Red Lock(红锁),会对所有实例申请加锁,超过半数节点加锁成功,红锁申请成功,反之失败。这样及时主节点挂掉,也不会对我们的锁产生影响。

我们上述方案可以解决2,3两问。

Released under the MIT License.