package com.lixiang.controller;
import org.redisson.RedissonRedLock;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.TimeUnit;
/**
* @author lixiang
* @date 2023/6/25 11:04
*/
@RestController
@RequestMapping("/")
public class RedLockController {
/**
* 定义锁的名字
*/
public static final String CACHE_KEY_REDLOCK = "redlock";
@Autowired
private RedissonClient redissonClient1;
@Autowired
private RedissonClient redissonClient2;
@Autowired
private RedissonClient redissonClient3;
@RequestMapping("getRedLock")
public String getRedLock(){
//每个客户端分别获取锁资源
RLock lock1 = redissonClient1.getLock(CACHE_KEY_REDLOCK);
RLock lock2 = redissonClient2.getLock(CACHE_KEY_REDLOCK);
RLock lock3 = redissonClient3.getLock(CACHE_KEY_REDLOCK);
//创建红锁 客户端
RedissonRedLock redLock = new RedissonRedLock(lock1, lock2, lock3);
//定义获取锁标志位,默认是获取失败
boolean isLockBoolean = false;
try {
/**
* waitTime:等待获取锁的最长时间。如果在等待时间内无法获取锁,并且没有其他锁释放,则返回 false。如果 waitTime < 0,则无限期等待,直到获得锁定。
* leaseTime:就是redis key的过期时间,锁的持有时间,可以使用 ttl 查看过期时间。
* 如果在持有时间结束前锁未被释放,则锁将自动过期,没有进行key续期,并且其他线程可以获得此锁。如果 leaseTime = 0,则锁将永久存在,直到被显式释放。
*/
isLockBoolean = redLock.tryLock(1, 20, TimeUnit.SECONDS);
System.out.printf("线程:"+Thread.currentThread().getId()+",是否拿到锁:" +isLockBoolean +"\n");
if (isLockBoolean) {
System.out.println("线程:"+Thread.currentThread().getId() + ",加锁成功,进入业务操作");
try {
//业务逻辑,40s模拟,超过了key的过期时间
TimeUnit.SECONDS.sleep(40);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} catch (Exception e) {
System.err.printf("线程:"+Thread.currentThread().getId()+"发生异常,加锁失败");
e.printStackTrace();
} finally {
// 无论如何,最后都要解锁
redLock.unlock();
}
return isLockBoolean?"success":"fail";
}
}
案例实战-SpringBoot整合Redisson实现RedLock分布式锁同步
需积分: 0 44 浏览量
更新于2023-06-26
1
收藏 18KB ZIP 举报
在分布式系统中,数据一致性与并发控制是至关重要的问题,而分布式锁作为一种常见的解决方案,能够有效地协调多个服务实例对共享资源的访问。本教程将基于SpringBoot框架,结合Redisson库来实现RedLock分布式锁,确保高可用性和数据一致性。
让我们了解SpringBoot。SpringBoot是由Pivotal团队提供的全新框架,它简化了基于Spring的应用程序开发过程,通过自动配置、起步依赖和内嵌服务器,使得开发者可以快速创建独立运行的、生产级别的基于Spring的应用。
接下来,我们引入Redisson,这是一个全面的Java客户端,提供了丰富的Redis功能,包括分布式锁、队列、信号量等。RedLock是Redisson中的一个特性,它由Redis社区提出,旨在提供一种更健壮的分布式锁实现,比单节点Redis的`setnx`命令更可靠。
RedLock的实现基于以下假设:
1. 时钟偏移:所有参与的Redis服务器的时钟大致同步。
2. 多副本:至少有五台Redis服务器,且部署在不同的硬件和网络上,以减少单点故障的风险。
3. 锁超时:每个锁都有超时设置,以防客户端异常导致锁无法释放。
在SpringBoot项目中整合Redisson,我们需要以下几个步骤:
1. 添加Redisson和Spring Boot的Redis starter依赖到`pom.xml`文件。
2. 配置Redisson客户端,包括连接池、服务器地址等。
3. 创建RedissonClient的Bean,以便Spring容器管理。
4. 使用Redisson提供的API来获取和释放RedLock。
以下是关键代码示例:
```java
@Configuration
public class RedissonConfig {
@Value("${redis.address}")
private String redisAddress;
@Bean(destroyMethod = "shutdown")
public RedissonClient redisson() {
Config config = new Config();
config.useSingleServer().setAddress(redisAddress);
return Redisson.create(config);
}
}
@Service
public class DistributedLockService {
@Autowired
private RedissonClient redisson;
public boolean acquireLock(String lockKey, long leaseTime) {
RLock lock = redisson.getLock(lockKey);
try {
if (lock.tryLock(5, TimeUnit.SECONDS, leaseTime, TimeUnit.SECONDS)) {
return true;
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
lock.unlock();
}
return false;
}
public void releaseLock(String lockKey) {
RLock lock = redisson.getLock(lockKey);
lock.unlock();
}
}
```
在上述代码中,我们创建了一个`DistributedLockService`,提供了获取和释放锁的方法。`acquireLock`尝试在指定时间内获取锁,如果成功则返回`true`,否则返回`false`。`releaseLock`方法负责解锁。
在实际应用中,我们可以根据业务需求,调用`DistributedLockService`的接口来控制对共享资源的访问,确保在分布式环境下的线程安全。
总结,本教程通过SpringBoot与Redisson的整合,详细介绍了如何使用RedLock实现分布式锁,包括SpringBoot项目配置、Redisson客户端设置以及具体使用示例。这种方式为高并发场景提供了可靠的并发控制,确保了分布式系统的稳定性和数据一致性。通过学习和实践这个案例,你可以更好地理解和应用分布式锁机制。