redisson的实现和优缺点

目录

1.可重入问题:

2.可重试问题:

3.超时释放:

4.主从一致性问题:

5.redisson的优缺点:

  Redisson 的优点:

  Redisson 的缺点:


Redisson 是一个基于 Redis 的 Java 驻内存数据网格解决方案,提供了丰富的分布式数据结构和功能,能够有效地解决可重入、可重试、超时释放以及主从一致性等问题。

1.可重入问题:

   Redisson 基于存放线程标识和重入次数的机制来实现可重入的分布式锁。下面是 Redisson 可重入锁的基本原理:

  1. 存放线程标识: 当一个线程获取了 Redisson 的可重入锁时,Redisson 会将该线程的标识(如线程 ID 或其他唯一标识)存放在 Redis 的一个特定的 key 下,作为锁的持有者标识。

  2. 重入次数: 同时,Redisson 还会维护一个重入次数计数器,用于记录当前线程已经重入加锁的次数。

通过存放线程标识和重入次数,Redisson 可以实现以下功能:

  • 当同一个线程再次获取可重入锁时,Redisson 会检查当前线程的标识和重入次数,如果匹配则允许重入加锁,重入次数加一。
  • 当释放锁时,Redisson 会根据当前线程的标识和重入次数,进行相应的减少操作,直到重入次数为零时才真正释放锁。

下面是一个伪代码示例,演示了 Redisson 可重入锁的基本原理:

class RedissonReentrantLock {
    // 用于存放线程标识的 Redis 键名
    String lockKey = "reentrant_lock";

    // 获取可重入锁
    public void lock() {
        String currentThreadId = Thread.currentThread().getId();
        int currentCount = getCountFromRedis(currentThreadId);
        if (currentCount > 0 && isCurrentThread(currentThreadId)) {
            // 已经持有锁,重入次数加一
            updateCountInRedis(currentThreadId, currentCount + 1);
        } else {
            // 尝试加锁
            if (tryAcquireLockInRedis()) {
                // 加锁成功,存放线程标识和设置重入次数为一
                storeThreadIdInRedis(currentThreadId);
                storeCountInRedis(currentThreadId, 1);
            } else {
                // 加锁失败,进行等待或重试
                // ...
            }
        }
    }

    // 释放锁
    public void unlock() {
        String currentThreadId = Thread.currentThread().getId();
        int currentCount = getCountFromRedis(currentThreadId);
        if (currentCount == 1) {
            // 重入次数为一时,真正释放锁
            releaseLockInRedis();
            removeThreadIdFromRedis(currentThreadId);
            removeCountFromRedis(currentThreadId);
        } else if (currentCount > 1) {
            // 重入次数减一
            updateCountInRedis(currentThreadId, currentCount - 1);
        } else {
            // 锁已释放或非法操作
        }
    }
}

以上伪代码示例演示了 Redisson 可重入锁的基本流程,包括存放线程标识和重入次数的维护以及加锁和释放锁的逻辑。使得同一个线程可以多次重入加锁,并在释放锁时正确地维护重入次数,确保了分布式环境下的可重入锁的正确性和可靠性。

2.可重试问题:

Redisson 基于信号量(Semaphore)和发布/订阅(Pub/Sub)实现了分布式锁的重试机制。以下是 Redisson 使用信号量和发布/订阅的方式来实现锁的重试机制的简要描述:

  1. 基于信号量的重试机制: Redisson 的分布式锁在获取锁时,可以通过信号量设置超时时间和重试等待时间,从而实现重试机制。当一个线程要获取分布式锁时,如果在指定的超时时间内未能获取到锁,它可以释放锁,并等待一段时间后再次尝试获取锁。

  2. 基于发布/订阅的重试机制: 在 Redisson 的分布式锁获取失败时,可以通过发布/订阅机制进行订阅失败通知。当一个线程获取锁失败后,可以订阅一个特定的频道或主题,用于接收锁的释放或超时等消息,以便进行重新尝试获取锁。

这两种机制可以结合使用,使得 Redisson 的分布式锁在获取失败后,可以进行重试操作。下面是一个简单的伪代码示例,演示了 Redisson 使用信号量和发布/订阅机制实现锁的重试机制:

RLock lock = redisson.getLock("myLock");

boolean isLocked = false;
try {
    isLocked = lock.tryLock(100, 10, TimeUnit.MILLISECONDS);
    // 尝试获取锁,超时时间 100 毫秒,重试等待时间 10 毫秒
    if (!isLocked) {
        // 获取锁失败,订阅重试频道
        RPatternTopic<String> retryChannel = redisson.getPatternTopic("lockRetryChannel");
        int retryCount = 0;
        while (!isLocked && retryCount < 3) {
            // 接收重试频道的消息
            retryChannel.addListener((channel, message) -> {
                // 收到重试消息后,再次尝试获取锁
                if (!isLocked) {
                    isLocked = lock.tryLock(100, 10, TimeUnit.MILLISECONDS);
                }
            });
            // 等待重试消息
            Thread.sleep(20);
            retryCount++;
        }
    }
} finally {
    if (isLocked) {
        lock.unlock();
    }
}

在上述示例中,当线程在指定时间内未能获取到锁时,它会订阅一个重试频道来接收重试消息,然后进行再次尝试获取锁。

通过信号量和发布/订阅机制的结合使用,Redisson 实现了分布式锁的重试机制,使得在获取锁时可以进行自动的重试操作,提高了分布式锁的可靠性和稳定性。

3.超时释放:

Redisson在处理锁的超时释放方面基于watchdog机制来实现。该机制使用了Redis的Sorted Set数据结构和Redis的过期键监控,以确保在锁超时后能够及时释放。

下面是Redisson基于watchdog解决超时释放的简要原理描述:

  1. 使用Sorted Set记录锁的过期时间:在获取分布式锁时,Redisson会将锁的信息(如锁名称、过期时间等)存储在Redis的Sorted Set集合中,以过期时间作为分数。这样,就可以根据过期时间将锁进行排序。

  2. 启动Watchdog线程监控锁的过期时间:Redisson会启动一个Watchdog线程,定期检查Sorted Set集合中的锁的过期时间。如果发现有锁已经过期,Watchdog线程将向Redis发布一个消息,通知需要释放这个锁。

  3. 监听消息并释放锁:订阅Redis发布的消息的监听者会接收到关于锁超时释放的消息,并执行相应的释放锁的操作。

通过以上机制,Redisson实现了对分布式锁的超时释放功能。这种方式保证了分布式锁在超时后能够及时释放,避免了死锁和资源占用的问题。

下面是一个简单的伪代码示例,演示了Redisson基于watchdog解决超时释放的机制:

RLock lock = redisson.getLock("myLock");

lock.lock(30, TimeUnit.SECONDS); // 获取锁,设置30秒超时时间

// 业务逻辑处理

lock.unlock(); // 释放锁

在上述示例中,通过设置锁的超时时间,Redisson会自动启动Watchdog线程来监控锁的超时情况,一旦锁超时,Watchdog将发布消息通知需要释放超时的锁。

4.主从一致性问题:

Redisson的MultiLock是一种可以同时锁定多个分布式锁的机制,可以用于解决主从一致性问题。通过MultiLock,可以确保跨多个 Redis 节点(主从)同时获取锁,以实现主从一致性。

下面是Redisson基于MultiLock实现主从一致性的简要原理描述:

  1. 创建 MultiLock 对象:在需要进行操作的时候,创建一个MultiLock对象,并指定需要加锁的多个锁。

  2. 尝试获取所有锁:调用MultiLock对象的tryLock方法来尝试获取所有的锁,如果成功获取所有锁,则表明跨多个 Redis 节点上的主从节点都成功获取了锁。

  3. 执行业务逻辑:一旦MultiLock成功获取所有锁,就可以执行相应的业务逻辑。

  4. 释放所有锁:在业务逻辑完成之后,必须调用MultiLock对象的unlock方法来释放所有的锁,以确保释放对应所有锁的资源。

通过以上的操作,可以确保在跨多个 Redis 节点上的主从节点上能够同时获取锁,从而实现主从一致性。下面是一个简单的伪代码示例,演示了Redisson基于MultiLock实现主从一致性的机制:

RLock lock1 = redisson.getLock("myLock1");
RLock lock2 = redisson.getLock("myLock2");
MultiLock multiLock = new MultiLock(lock1, lock2);

boolean isLocked = multiLock.tryLock();
if (isLocked) {
    try {
        // 执行业务逻辑
    } finally {
        multiLock.unlock();
    }
} else {
    // 未能同时获取所有锁,执行相应的处理逻辑
}

在上述示例中,通过MultiLock尝试同时获取多个锁,如果成功获取所有锁,则执行业务逻辑,最后释放所有的锁。通过这种方式,可以确保在分布式环境下跨多个 Redis 节点上的主从节点同时获取锁,从而实现主从一致性。

5.redisson的优缺点:

  Redisson 的优点:

  1. 易用性:Redisson 提供了简单易用的 API,方便开发人员在 Java 项目中使用 Redis 的分布式功能,无需过多的复杂配置。
  2. 丰富的功能:Redisson 支持丰富的分布式数据结构,如队列、锁、集合等,能够满足多样化的分布式应用需求。
  3. 高可用性:Redisson 提供了对 Redis 的高可用性支持,能够应对 Redis 节点故障和网络分区等问题。

Redisson 的缺点:

  1. 性能开销:与直接使用原生的 Redis Java 客户端相比,Redisson 在某些场景下可能会引入额外的性能开销,因为其实现了丰富的高级功能。
  2. 学习成本:对于初次使用者来说,可能需要一定的学习成本来熟悉 Redisson 的各种功能和用法。
  3. 依赖性:使用 Redisson 会引入对 Redisson 库的依赖,需要确保依赖的稳定性和维护更新。

总体来说,Redisson 是一个功能丰富且易用的 Redis 客户端,适用于需要在 Java 项目中快速构建分布式应用的场景。在选择是否使用 Redisson 时,可以根据具体的项目需求和性能要求进行权衡。

  • 31
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值