分布式锁 Redission

Redisson 是一个基于 Redis 的 Java 分布式框架,提供了丰富的分布式锁功能,包括 可重入锁、公平锁、联锁(MultiLock)、红锁(RedLock) 等。以下是详细说明:


1. Redisson 锁的类型

(1)可重入锁(Reentrant Lock)重点锁!!最经常用的锁!!

  • 特点:同一个线程可以重复获取锁(避免死锁),利用hash结构记录线程id和重入次数。

  • 默认锁类型:Redisson 的 RLock 默认就是 可重入锁

    图1 可重入锁流程图(来源黑马)
    • Lock("lock:order:" + userId;){

             threadID : 1 (锁里面只能有该线程ID可以进行重入+1-1的操作)

      }

      hash结构:锁的名字key :: 第一个获取锁的threadID :: 重入次数value;

  • 示例

    RLock lock = redisson.getLock("myLock");
    try {
        lock.trylock();      // 加锁(可重入)
        // trylock参数:1.获取锁的最大等待时间、2.锁自动释放时间,3.单位。 
        // 业务逻辑
    } finally {
        lock.unlock(); // 释放锁
    }

(2)公平锁(Fair Lock)

  • 特点:按请求顺序分配锁(避免饥饿问题)。

  • 实现:基于 Redis 的队列机制。

  • 示例

    RLock fairLock = redisson.getFairLock("fairLock");
    fairLock.lock();  // 公平加锁

(3)联锁(MultiLock)

  • 特点

    1. 锁定多个不同的资源,原子性锁定多个资源(如订单+库存+优惠券),保证这些资源的操作要么全部成功,要么全部失败。

    2. 所有锁必须在同一个 Redis 集群内(不能跨不同集群或独立节点)

  • 用途:多资源事务场景。

  • 示例

    RLock orderLock = redisson.getLock("order:123");
    RLock stockLock = redisson.getLock("stock:456");
    RLock couponLock = redisson.getLock("coupon:789");
    ​
    // 联锁:必须同时锁定 order、stock、coupon
    RLock multiLock = redisson.getMultiLock(orderLock, stockLock, couponLock);
    multiLock.lock(); // 只有三个锁都成功才算加锁成功。
  • 题外话:图1、2来源黑马点评,说Mutilock锁能解决主从一致问题,错误❌ !实际上能解决这个问题的是(4)redLock
  • 什么是主从一致问题:当 Redis 主节点加锁成功后,如果锁数据未同步到从节点,而主节点突然宕机,从节点晋升为新主节点后,锁状态丢失,导致多个客户端同时持有锁,破坏互斥性

        举个例子:

  1. 假设 Redis 采用 一主一从 架构:
  2. 客户端 A 向 主节点 申请锁 lock:order,加锁成功。
  3. 主节点 还未将锁数据同步给 从节点,就突然宕机。
  4. 从节点 自动晋升为 新主节点,但此时它没有 lock:order 的记录。
  5. 客户端 B 向 新主节点 申请同一把锁 lock:order,加锁成功。

          结果:客户端 A 和客户端 B 同时持有锁,导致数据竞争或业务错误。

图2 来自黑马点评的联锁(处理主从一致问题)
图3 来自黑马点评的联锁(处理主从一致问题)

                                                                

(4)红锁(RedLock)

  • 特点

    1. 解决主从一致性问题:在 Redis 主从架构中,防止主节点宕机后锁信息丢失(从节点可能未同步锁数据)。

    2. 基于多节点投票机制:要求多数节点(N/2 + 1)加锁成功才算真正获取锁。

  • 原理

    1. 向多个 独立的 Redis 主节点(非主从关系)发送加锁请求。

    2. 只有 多数节点(≥ N/2 +1)加锁成功,才算获取锁成功。

    3. 即使部分节点宕机,锁依然有效。

  • 缺点

    • 时钟漂移问题:如果 Redis 节点间系统时钟不同步,可能导致锁提前失效。

      • 解决方案:使用单调时钟(如 redis.time())而非系统时钟。

    • 性能开销:需向多个节点发起加锁/解锁请求,延迟较高。

再次强调说明:这里的是多个独立的redis节点!而不是同一个集群的不同redis节点。

        单 Redis 实例/集群的锁

  • 传统方式:在单个 Redis 实例或集群中获取一把锁(如 SET lock_key uuid NX EX 30)。

  • 风险

    • 如果 Redis 主节点宕机,且锁数据未同步到从节点,新主节点可能丢失锁信息。

    • 集群模式下,锁的键可能分布在不同的分片,无法保证全局一致性。

        示例问题场景

  1. 客户端 A 在 Redis 主节点获取锁成功。

  2. 主节点宕机,从节点升级为新主节点,但锁数据未同步。

  3. 客户端 B 向新主节点申请同一把锁,错误地获取成功(导致两个客户端同时持有锁)。


        RedLock 的解决方案

         核心思想        

         分散风险:在多个完全独立的 Redis 节点(非主从关系)上同时申请锁,只有 多数节点(N/2 + 1) 加锁成功才算真正获取锁。

        数学保证:即使部分节点宕机或网络分区,仍能保证锁的安全性。

        具体流程

        假设部署 5 个独立 Redis 节点(N=5):

  1. 客户端向所有 5 个节点发送加锁请求(相同的键和随机值)。

  2. 每个节点独立执行加锁操作(SET key random_value NX PX 30000)。

  3. 客户端统计成功加锁的节点数:

    • ≥ 3 个(多数)成功 → 认为加锁成功。

    • < 3 个成功 → 向所有节点发送解锁请求(清理残留锁)。

  4. 锁的有效时间 = 初始 TTL - 加锁耗时(需时钟同步)。

  • 示例

    RLock lock1 = redisson1.getLock("order");
    RLock lock2 = redisson2.getLock("order");
    RLock lock3 = redisson3.getLock("order");
    RLock lock4 = redisson4.getLock("order");
    RLock lock5 = redisson5.getLock("order");
    RLock redLock = redisson.getRedLock(lock1, lock2, lock3, lock4, lock5);
    redLock.lock();  // 红锁加锁

2. Redisson 锁的默认行为

  • 默认锁类型redisson.getLock() 返回的是 可重入非公平锁

  • 看门狗机制:默认加锁 30 秒,并通过后台线程自动续期(避免业务未完成锁过期)。

  • 非阻塞尝试:可通过 tryLock() 实现非阻塞获取锁:

    
    
    	
    boolean res = lock.tryLock(10, 60, TimeUnit.SECONDS); // 等待10秒,锁60秒
    // 如果这里设置了锁的时间,就不会走看门狗机制了,到期释放锁。


3. 锁的特性对比

锁类型是否可重入是否公平适用场景
可重入锁(默认)✅ 是❌ 否通用分布式锁
公平锁✅ 是✅ 是需要按顺序获取锁的场景
联锁(MultiLock)✅ 是❌ 否多资源原子操作(如分库分表事务)
红锁(RedLock)✅ 是❌ 否高可用性要求(防单点故障)

4. 关键注意事项

  1. 锁释放:必须放在 finally 块中,否则可能导致死锁。

  2. 锁续期:默认通过看门狗线程自动续期(无需手动处理)。

  3. 红锁争议:RedLock 算法在实际生产中可能存在争议(如时钟漂移问题),建议仅在多数据中心场景使用。


总结

  • 默认锁:可重入非公平锁(RLock)。

  • 高级锁:公平锁、联锁、红锁按需选择。

  • 生产建议

    • 普通场景用默认锁即可。

    • 高可用场景可测试红锁(但需评估复杂度)。

    • 联锁适用于多资源事务。

Redisson 的锁实现是生产级分布式系统的首选方案,合理使用能有效解决并发问题!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值