如何用Redisson实现分布式锁?

[Q&A] 什么是Redisson?

Redisson 是一个基于 Java 的高级 Redis 客户端,它提供了丰富的数据结构分布式服务。是一个中间件。


[Q&A] 如何用Redisson实现分布式锁?

<dependencies>
    <dependency>
        <groupId>org.redisson</groupId>
        <artifactId>redisson</artifactId>
        <version>3.17.5</version>
    </dependency>
</dependencies>
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;

import java.util.concurrent.TimeUnit;

public class RedissonDistributedLockExample {

    public static void main(String[] args) throws InterruptedException {
        // 创建Redisson客户端连接
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");
        RedissonClient redisson = Redisson.create(config);

        // 获取分布式锁对象
        RLock lock = redisson.getLock("myLock");

        try {
            lock.lock(); // 加锁
            lock.lock(10, TimeUnit.SECONDS); // 加锁,最多等待10秒,加锁成功后持有锁30秒
            
            // ... 在这里执行临界区代码
        } finally {
            // 无论如何都要确保最终释放锁
            lock.unlock();
        }

        // 关闭Redisson客户端连接
        redisson.shutdown();
    }
}

[Q&A] 如何用Redisson实现公平锁?

import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.config.Config;

public class RedissonFairLockExample {

    public static void main(String[] args) {
        // 创建Redisson配置并连接到Redis
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");
        RedissonClient redisson = Redisson.create(config);

        // 获取名为"myFairLock"的公平锁
        RLock fairLock = redisson.getFairLock("myFairLock");

        try {
            // 尝试获取公平锁
            fairLock.lock();

            System.out.println("线程 " + Thread.currentThread().getName() + " 获得了公平锁");
            // 在这里执行临界区代码
        } finally {
            // 无论如何都要确保最终释放锁
            if (fairLock.isLocked()) {
                fairLock.unlock();
            }
        }

        // 关闭Redisson客户端连接
        redisson.shutdown();
    }
}

[Q&A] 如何用Redisson实现联锁?

在分布式系统中,我们通常所说的“联锁”或“联合锁”(Multi-locking)指的是在一次操作中需要获取多个分布式锁的情况。

import org.redisson.Redisson;
import org.redisson.api.RLock;

public class RedissonMultiLockExample {

    public static void main(String[] args) {
        // 创建Redisson客户端连接
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");
        RedissonClient redisson = Redisson.create(config);

        // 获取两个分布式锁
        RLock lock1 = redisson.getLock("lock1");
        RLock lock2 = redisson.getLock("lock2");

        try {
            // 同时获取两个锁
            // 这里假设lock1和lock2需要同时获取才能进入临界区
            if (lock1.tryLock() && lock2.tryLock()) {
                System.out.println("线程 " + Thread.currentThread().getName() + " 成功获取了lock1和lock2");
                // 在这里执行需要同时锁定两个资源的操作
            } else {
                System.out.println("线程 " + Thread.currentThread().getName() + " 未能同时获取lock1和lock2");
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            System.out.println("获取锁时被打断");
        } finally {
            // 无论如何都要确保解锁,先解锁不影响获取顺序
            if (lock1.isLocked() && lock1.isHeldByCurrentThread()) {
                lock1.unlock();
            }
            if (lock2.isLocked() && lock2.isHeldByCurrentThread()) {
                lock2.unlock();
            }
        }

        // 关闭Redisson客户端连接
        redisson.shutdown();
    }
}

[Q&A] 如何用Redisson实现RedLock ?

RedLock 是 Redis 的作者 Salvatore Sanfilippo 提出的一种分布式锁算法,它通过在多个独立的 Redis 实例上同时获取锁来提高锁的安全性和可用性。

Redisson 作为 Redis Java 客户端库,实现了 RedLock 算法。

import org.redisson.Redisson;
import org.redisson.api.*;
import org.redisson.config.Config;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class RedLockAlgorithmExample {

    public static void main(String[] args) throws InterruptedException {
        // 假设我们有五个独立的Redis节点地址
        List<String> addresses = Arrays.asList(
                "redis://127.0.0.1:6379",
                "redis://127.0.0.1:6380",
                "redis://127.0.0.1:6381",
                "redis://127.0.0.1:6382",
                "redis://127.0.0.1:6383");

        Config config = new Config();
        config.useClusterServers()
              .addNodeAddress(addresses.toArray(new String[0]))
              .setScanInterval(2000); // 设置扫描间隔用于集群模式

        RedissonClient redisson = Redisson.create(config);

        try {
            // 定义资源名称和锁的超时时间
            String resourceName = "myResource";
            int lockLeaseTime = 5; // 锁的有效时长,单位为秒
            int clockDriftFactor = 0.01; // 时钟漂移因子
            int retryCount = 3; // 重试次数

            // 创建各个Redis实例上的锁实例
            RLock[] locks = new RLock[addresses.size()];
            for (int i = 0; i < addresses.size(); i++) {
                locks[i] = redisson.getLock(resourceName + "-" + i);
            }

            // 创建RedLock工具类
            RedLock redLock = new RedLock(locks);

            // 尝试获取锁
            boolean isLockAcquired = redLock.tryLock(lockLeaseTime, clockDriftFactor * lockLeaseTime, TimeUnit.SECONDS, retryCount);

            if (isLockAcquired) {
                System.out.println("Lock on '" + resourceName + "' successfully acquired using Redlock algorithm.");

                // 在此执行临界区代码...

                // 最后释放锁
                redLock.unlock();
            } else {
                System.out.println("Failed to acquire the lock within the specified parameters.");
            }
        } finally {
            // 关闭Redisson客户端连接
            redisson.shutdown();
        }
    }
}

[Ref] 什么是RedLock,他解决了什么问题?


[Q&A] 如何用Redisson实现读写锁?

Redisson 的读写锁与 Java 的 ReentrantReadWriteLock 类似,支持多个读锁同时获取,但写锁只能由一个线程获取。

import org.redisson.Redisson;
import org.redisson.api.RReadWriteLock;
import org.redisson.config.Config;

import java.util.concurrent.TimeUnit;

public class RedissonReadWriteLockExample {

    public static void main(String[] args) {
        // 创建 Redisson 客户端配置
        Config config = new Config();
        config.useSingleServer().setAddress("redis://localhost:6379");

        // 创建 Redisson 客户端实例
        RedissonClient redisson = Redisson.create(config);

        // 创建 Redisson 读写锁实例
        RReadWriteLock readWriteLock = redisson.getReadWriteLock("myLock");

        // 获取读锁并执行读操作
        readWriteLock.readLock().lock();
        try {
            System.out.println("Reading data...");
            // 执行读操作
        } finally {
            readWriteLock.readLock().unlock();
        }

        // 获取写锁并执行写操作
        readWriteLock.writeLock().lock();
        try {
            System.out.println("Updating data...");
            // 执行写操作
        } finally {
            readWriteLock.writeLock().unlock();
        }

        // 关闭 Redisson 客户端实例
        redisson.shutdown();
    }
}

[Q&A] 什么是单点故障?
单点故障是指在一个系统中,某个组件或节点的故障会导致整个系统的崩溃或无法正常工作的情况。

[Q&A] RedLock 可以解决什么问题?
在分布式系统中,由于多个节点之间的网络延迟、故障、竞争等因素,可能会导致死锁、数据不一致等问题。RedLock 算法通过在多个节点之间加锁来保证共享资源的访问顺序一致性,从而避免这些问题的发生。

还可以统计加锁成功数来解决单点故障问题。


[Ref] 如何用Redisson实现分布式锁?

  • 29
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Redisson是一个基于Redis的Java驻留库,它提供了许多分布式对象和服务,其中包括分布式锁Redisson分布式锁实现是基于Redis的单实例或集群模式,它提供了两种方式来获取分布式锁: 1.手动使用分布式锁:通过获取锁对象,然后尝试获取锁,如果获取到锁则执行业务逻辑,否则直接抛出异常。最后释放锁。 2.获取到分布式锁返回布尔值:通过获取锁对象,然后尝试获取锁,如果获取到锁则返回true,否则返回false。根据返回值来判断是否获取到锁,然后执行相应的业务逻辑。最后释放锁。 下面是两种方式的示例代码: 1.手动使用分布式锁 ```java @Autowired private LockUtils lockUtils; public void testLock(String key){ //获取锁对象 RLock lockObj = lockUtils.getLockObj(key); try { //尝试获取锁、如果他获取到锁继续执行代码逻辑,若果获取不到会抛出异常 lockUtils.tryLock(lockObj); System.out.println("获取到锁"); //执行业务逻辑 //... }finally { //释放锁 lockUtils.unLock(lockObj); } } ``` 2.获取到分布式锁返回布尔值 ```java @Autowired private LockUtils lockUtils; public void testLock(String key){ //获取锁对象 RLock lockObj = lockUtils.getLockObj(key); try { //尝试获取锁、如果他获取到锁继续执行代码逻辑,若果获取不到会抛出异常 boolean lock = lockUtils.getLock(lockObj); if (lock){ //获取到锁处理的事(业务逻辑) System.out.println("获取到锁"); //执行业务逻辑 //... }else { //没有获取到锁自己想处理的事 System.out.println("没有获取到锁"); //执行其他逻辑 //... } }finally { //释放锁 lockUtils.unLock(lockObj); } } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值