Redisson分布式锁框架

        Redisson是一个用于Redis的Java客户端,它极大地简化了分布式锁、分布式集合、分布式服务等复杂场景下的开发工作。Redisson提供了丰富的功能,并且对分布式锁的支持尤为强大和灵活。

引入依赖

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.20.0</version>
</dependency>

创建配置类

@Configuration
public class RedissonConfig {

    @Bean("redissonClient")
    public RedissonClient redissonClient() {
        Config config = new Config();
        String redisHost = "127.0.0.1";
        String password = "Aa123456@";
        Integer port = 6379;
        int dbNo = 0;
        config.useSingleServer()
                .setAddress("redis://" + redisHost + ":" + port)
                .setDatabase(dbNo)
                .setPassword(password);
        // 创建RedissonClient对象
        return Redisson.create(config);
    }

}

方式1:基本使用(自动续期)
lock.lock();

方式2:指定租约时间(无自动续期)
对象.lock(10, TimeUnit.SECONDS);

方式3:尝试获取锁(推荐)
boolean acquired = 对象.tryLock(10, 30, TimeUnit.SECONDS);

1.可重入锁(Reentrant Lock)

        是最常用的锁类型之一,类似于Java中的ReentrantLock。

        在某些复杂的业务逻辑中,一个方法可能会调用另一个方法,而这两个方法都需要获取同一把锁。如果使用普通的锁,线程在第一次获取锁后,再次尝试获取锁时会被阻塞。可重入锁允许同一个线程多次获取锁,避免了这种情况。

    private RedissonClient redissonClient;

    public void performTask() throws InterruptedException {
        RLock lock = redissonClient.getLock("myLock");
        try {
            // 尝试获取锁,最多等待10秒,持有锁的时间为60秒
            boolean isLocked = lock.tryLock(10, 60, TimeUnit.SECONDS);
            if (isLocked) {
                // 执行业务逻辑
            }
        } finally {
            lock.unlock(); // 确保释放锁
        }
    }

2.公平锁(Fair Lock)

        公平锁确保所有请求按照它们到达的顺序获取锁,避免“饥饿”现象。

    private RedissonClient redissonClient;

    public void performTask() throws InterruptedException {
        RLock fairLock = redissonClient.getFairLock("myFairLock");

        try {
            fairLock.lock(10, TimeUnit.SECONDS); // 获取锁并设置最大等待时间
            //fairLock.tryLock(10,60,TimeUnit.SECONDS);
            // 执行业务逻辑
        } finally {
            fairLock.unlock();
        }
    }

3.读写锁(ReadWriteLock)

        读写锁允许多个线程同时读取数据,但在写入时提供独占访问。

    private RedissonClient redissonClient;

    public void read() throws InterruptedException {
        //获取读写锁对象
        RReadWriteLock rwLock = redissonClient.getReadWriteLock("myReadWriteLock");

        rwLock.readLock().lock();
        try {
            // 执行读操作
        } finally {
            rwLock.readLock().unlock();
        }
    }

    public void write() throws InterruptedException {
        //获取读写锁对象
        RReadWriteLock rwLock = redissonClient.getReadWriteLock("myReadWriteLock");

        rwLock.writeLock().lock();
        try {
            // 执行写操作
        } finally {
            rwLock.writeLock().unlock();
        }
    }

4.联锁(MultiLock)

        联锁是一种同步机制,用于同时获取多个锁。在分布式系统中,当需要对多个独立资源进行操作时,联锁确保所有的资源都被锁定,以进行安全的原子操作。

    private RedissonClient redissonClient;
    
    public void performTask() throws InterruptedException {
        RLock lock1 = redissonClient.getLock("lock1");
        RLock lock2 = redissonClient.getLock("lock2");

        RLock multiLock = redissonClient.getMultiLock(lock1, lock2);

        try {
            multiLock.lock();
            // 执行业务逻辑
        } finally {
            multiLock.unlock();
        }
    }

5.自旋锁(Spin Lock)

        自旋锁是一种非阻塞锁,线程在获取锁时会不断尝试,直到成功为止。

    private RedissonClient redissonClient;

    public void performTask() throws InterruptedException {
        RLock spinLock = redissonClient.getSpinLock("mySpinLock");
        try {
            spinLock.lock();
            // 执行业务逻辑
        } finally {
            spinLock.unlock();
        }
    }

7.红锁(RedLock)

        在多个独立的 Redis 节点上同时获取锁,只有当大多数节点(N/2 + 1)都成功获取锁时,才认为锁获取成功。

        备注:当你在类的构造器、字段(成员变量)或 setter 方法上使用 @Autowired 时,Spring 容器会尝试找到匹配的 Bean 并将其注入到相应的属性中。这极大地简化了对象之间的依赖管理,减少了样板代码,并提高了代码的可维护性和灵活性。

        创建多节点配置类

@Configuration
public class RedissonConfig {
    @Bean(name = "client1", destroyMethod = "shutdown")
    public RedissonClient createClient1() {
        Config config = new Config();
        config.useSingleServer()
                .setAddress("redis://127.0.0.1:6379")
                .setPassword("password1") // 如果有密码
                .setDatabase(0); // 选择数据库
        return Redisson.create(config);
    }

    @Bean(name = "client2", destroyMethod = "shutdown")
    public RedissonClient createClient2() {
        Config config = new Config();
        config.useSingleServer()
                .setAddress("redis://127.0.0.1:6380")
                .setPassword("password2") // 如果有密码
                .setDatabase(0); // 选择数据库
        return Redisson.create(config);
    }

    @Bean(name = "client3", destroyMethod = "shutdown")
    public RedissonClient createClient3() {
        Config config = new Config();
        config.useSingleServer()
                .setAddress("redis://127.0.0.1:6381")
                .setPassword("password3") // 如果有密码
                .setDatabase(0); // 选择数据库
        return Redisson.create(config);
    }
}

        实现工具类

@Component
public class RedissonUtil {

    private final RedissonClient client1;
    private final RedissonClient client2;
    private final RedissonClient client3;

    @Autowired
    public RedissonUtil(@Qualifier("client1") RedissonClient client1,
                        @Qualifier("client2") RedissonClient client2,
                        @Qualifier("client3") RedissonClient client3) {
        this.client1 = client1;
        this.client2 = client2;
        this.client3 = client3;
    }

    public boolean tryRedLock(String lockName, long waitTime, long leaseTime, TimeUnit timeUnit) {
        RLock lock1 = client1.getLock(lockName);
        RLock lock2 = client2.getLock(lockName);
        RLock lock3 = client3.getLock(lockName);

        RLock redLock = client1.getRedLock(lock1, lock2, lock3);

        try {
            return redLock.tryLock(waitTime, leaseTime, timeUnit);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return false;
        }
    }

    public void releaseRedLock(String lockName) {
        RLock lock1 = client1.getLock(lockName);
        RLock lock2 = client2.getLock(lockName);
        RLock lock3 = client3.getLock(lockName);

        RLock redLock = client1.getRedLock(lock1, lock2, lock3);
        if (redLock.isLocked() && redLock.isHeldByCurrentThread()) {
            redLock.unlock();
        }
    }
}

        代码示例

@Service
public class RedisService {

    private final RedissonUtil redissonUtil;

    @Autowired
    public RedisService(RedissonUtil redissonUtil) {
        this.redissonUtil = redissonUtil;
    }

    public void performTask() throws InterruptedException {
        boolean isLocked = redissonUtil.tryRedLock("myRedLock", 100, 10, TimeUnit.SECONDS);
        if (isLocked) {
            try {
                System.out.println("RedLock acquired successfully!");
                // 执行业务逻辑
                Thread.sleep(1000L);
            } finally {
                redissonUtil.releaseRedLock("myRedLock");
                System.out.println("RedLock released!");
            }
        } else {
            System.out.println("Failed to acquire RedLock!");
        }
    }
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值