分布式锁实战:Redisson看门狗机制与RedLock争议落地

分布式系统里多个实例同时操作共享资源,数据库唯一约束、乐观锁都失效时,分布式锁是最后的防线。Redis实现分布式锁看起来就是SETNX一行命令,生产事故却频发:锁过期但业务没执行完、解锁解掉别人的锁、主从切换锁丢失。Redisson框架把这些问题用看门狗机制和可重入设计逐一处理,理解其内部机制才能判断什么场景能用、什么场景必须换方案。

Redis分布式锁的正确加锁姿势

错误写法是先SETNX再EXPIRE,两条命令之间进程崩溃,锁永远无法释放。正确做法是SET命令带NX和EX参数原子完成:

# 加锁:key不存在才设置,同时给10秒过期
SET lock:order:1001  NX EX 10

value必须是每次请求的唯一标识,常见用UUID加线程ID。解锁必须用Lua脚本做条件删除,防止误删其他客户端的锁——A客户端业务超时锁自动过期,B客户端拿到锁,A恢复后直接DEL会把B的锁删掉,C客户端趁虚而入,锁完全失效:

-- 解锁脚本:值匹配才删除,保证只删自己的锁
if redis.call("get", KEYS[1]) == ARGV[1] then
    return redis.call("del", KEYS[1])
else
    return 0
end

手工实现到这一步仍然有缺陷:业务执行时间超过过期时间怎么办?过期时间设置多长合适?这些问题Redisson给出了系统答案。

Redisson看门狗机制:锁续期的实现原理

Redisson加锁不指定过期时间时自动启用看门狗。加锁成功后启动后台定时任务,每10秒(过期时间的三分之一)检查一次,锁还被当前客户端持有就续期到30秒。业务执行多久锁就活多久,执行结束显式解锁,看门狗随客户端断开自动停止。代码只有三行:

RLock lock = redisson.getLock("lock:order:1001");
lock.lock();   // 不传超时,启动看门狗
try {
    doBusiness();
} finally {
    lock.unlock();
}

看门狗的续期基于客户端到Redis的连接,客户端进程崩溃后定时任务消失,锁等30秒自然过期,不会死锁。需要注意lock(timeout, unit)传入超时时间的重载不启动看门狗——框架认为调用方自己管理生命周期,过期即释放。生产建议:拿不准执行时长用无参lock()配合看门狗;执行时间有硬上限且必须自动释放时才传超时。tryLock(waitTime, leaseTime, unit)用于快速失败场景,waitTime内拿不到锁直接返回false,避免请求堆积。

可重入锁与联锁多资源场景

Redisson的RLock实现可重入,同一线程重复加锁计数加一,解锁计数减一,归零才真正释放。这个设计兼容递归调用和AOP嵌套拦截的场景。多把锁保护多个资源用RedLock或多把锁对象:

RedissonClient redisson = Redisson.create(config);
RLock lockA = redisson.getLock("lock:account:A");
RLock lockB = redisson.getLock("lock:account:B");
RedissonMultiLock multiLock = new RedissonMultiLock(lockA, lockB);
multiLock.lock();
try {
    transfer(a, b);   // 同时锁定A、B两个账户
} finally {
    multiLock.unlock();
}

MultiLock是同时全拿或全不拿的语义,拿锁按顺序逐个获取,中途失败自动回滚已拿到的锁。拿锁顺序不一致会导致交叉死锁:事务一先拿A再拿B,事务二先拿B再拿A,互相等待。工程约束是锁key统一排序后按序获取,多资源场景在代码层用同一个工具方法收口。

主从切换丢锁与RedLock方案的取舍

Redis主从架构下,加锁写在主库,异步复制到从库。主库加锁成功后瞬间宕机,锁数据还没同步到从库,从库升主后其他客户端能再次加锁,两个客户端同时持有锁。Redis作者提出的RedLock方案部署N个独立主节点(至少5个),向过半节点加锁成功才算持有。该方案被分布式系统学者Martin Kleppmann公开质疑:时钟跳变、进程暂停会破坏互斥性保证,且N个节点成本高、语义复杂。工程上的务实选择分三档:一般业务(缓存更新、防重复提交)用主从Redisson单实例锁,偶发失效可接受;金额类关键操作锁只做性能优化、正确性兜底交给数据库行锁或唯一索引;跨资源转账正确性要求极高的场景,用ZooKeeper或etcd的强一致锁,牺牲一些延迟换取严格的互斥保证。锁的选型原则一句话:Redis锁提高效率,正确性不能只靠它。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/fen-bu-shi-suo-shi-zhan-redisson-kan-men-gou-ji-zhi-yu/

(0)
小编小编
上一篇 8小时前
下一篇 8小时前

相关推荐