Redisson 分布式锁的底层实现机制基于 Redis 的原子操作和 Lua 脚本,核心流程如下:

1. 加锁流程

  • Lua 脚本原子操作
    通过 EVAL 执行 Lua 脚本保证原子性,伪逻辑:

    if redis.call('exists', KEYS[1]) == 0 then 
        redis.call('hset', KEYS[1], ARGV[1], 1) 
        redis.call('pexpire', KEYS[1], ARGV[2]) 
        return 1 
    end
    

    • KEYS[1]:锁名称(如 my_lock
    • ARGV[1]:客户端唯一标识(UUID + 线程ID)
    • ARGV[2]:锁过期时间(毫秒)
  • 可重入性实现
    若锁已存在且持有者为当前客户端,则执行重入计数:

    if redis.call('hexists', KEYS[1], ARGV[1]) == 1 then 
        redis.call('hincrby', KEYS[1], ARGV[1], 1) 
        redis.call('pexpire', KEYS[1], ARGV[2]) 
        return 1 
    end
    

2. 锁续期机制(Watchdog)

  • 后台线程定时续期
    默认每 10 秒检查锁持有状态,若客户端仍活跃则重置过期时间:
    // 伪代码逻辑
    while (lockHeldByCurrentThread) {
        redis.expire(lockKey, leaseTime); 
        Thread.sleep(10000); // 10秒间隔
    }
    

    避免因业务执行时间过长导致锁意外失效。

3. 解锁流程

  • 原子化释放锁
    仅当锁持有者为当前客户端时,减少重入计数或删除锁:
    if redis.call('hexists', KEYS[1], ARGV[1]) == 0 then 
        return nil 
    end 
    local counter = redis.call('hincrby', KEYS[1], ARGV[1], -1) 
    if counter > 0 then 
        redis.call('pexpire', KEYS[1], ARGV[2]) 
        return 0 
    else 
        redis.call('del', KEYS[1]) 
        return 1 
    end
    

    • 重入计数归零时才删除锁 KEY

4. 关键特性保障

机制 实现方式 作用
互斥性 Redis 单线程模型 + SETNX 确保仅一个客户端持有锁
防死锁 过期时间 + Watchdog 续期 避免客户端崩溃导致锁永久占用
可重入 Hash 结构存储重入计数 同一线程多次加锁不阻塞
容错性 Redis 集群模式 (RedLock 算法) 主节点故障时自动切换

5. 高可用设计

  • RedLock 算法
    在 Redis 集群中,同时向 $N$ 个独立节点申请锁,当超过半数($\frac{N}{2}+1$)加锁成功时视为全局锁获取成功,公式:
    $$成功节点数 \geq \left\lfloor \frac{N}{2} \right\rfloor + 1$$

总结

Redisson 通过组合 Redis 原子操作、Lua 脚本、后台守护线程,实现了高可靠的分布式锁,解决了并发场景下的资源竞争问题,同时保障了互斥性、可重入性及系统容错能力。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐