实现分布式锁有四种方式:基于数据库实现分布式锁、基于redis实现分布式锁、基于zookeeper实现分布式锁、基于Redisson实现分布式锁。本文讲解的是基于redisson实现分布式锁,其它三种情况,大家可以自行百度学习。
实现步骤:
- 引入基本的依赖
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.10.6</version>
</dependency>
- 在application.properties文件配置redis集群地址
- 编写Redisson初始化类
RedissonConfig.java:
@Configuration
public class RedissonConfig {
@Bean
public RedissonClient getRedissonClient() throws IOException {
Resource resource = new ClassPathResource("redisson-config-file.json");
Config config = Config.fromJSON(resource.getInputStream());
RedissonClient redisson = Redisson.create(config);
return redisson;
}
}
redisson-config-file.json:
{
"clusterServersConfig":{
"idleConnectionTimeout":10000,
"pingTimeout":1000,
"connectTimeout":10000,
"timeout":3000,
"retryAttempts":3,
"retryInterval":1500,
"reconnectionTimeout":3000,
"failedAttempts":3,
"password":123456,
"subscriptionsPerConnection":5,
"clientName":null,
"loadBalancer":{
"class":"org.redisson.connection.balancer.RoundRobinLoadBalancer"
},
"slaveSubscriptionConnectionMinimumIdleSize":1,
"slaveSubscriptionConnectionPoolSize":50,
"slaveConnectionMinimumIdleSize":32,
"slaveConnectionPoolSize":64,
"masterConnectionMinimumIdleSize":32,
"masterConnectionPoolSize":64,
"readMode":"SLAVE",
"nodeAddresses":[
"redis://192.168.1.77:7001",
"redis://192.168.1.77:7004",
"redis://192.168.1.77:7007",
"redis://192.168.1.78:7002",
"redis://192.168.1.78:7005",
"redis://192.168.1.78:7008",
"redis://192.168.1.79:7003",
"redis://192.168.1.79:7006",
"redis://192.168.1.79:7009"
],
"scanInterval":1000
},
"threads":0,
"nettyThreads": 0,
"codec":null,
"transportMode":"NIO"
}
- 应用分布式锁
//使用分布式锁,锁住预约时间
String lockKey = date + "_" + appointmentParam.getAppointItems() + "_" + appointmentParam.getAppointDoctor();
RLock lock = redissonClient.getFairLock(lockKey);
boolean getLock = false;
try {
//获取锁成功
if (getLock = lock.tryLock(5, TimeUnit.SECONDS)) {
//判断该时间段是否被预约了
wrapper = new EntityWrapper();
wrapper.eq("book_start_time", parse);
wrapper.andNew().eq("status", AppointStatus.RESERVED.getType()).or().eq("status", AppointStatus.REFUND.getType());
appoint = this.selectOne(wrapper);
if (appoint != null) {
return JsonResult.getFailJsonResult("该时间段已被预约");
}
//新增预约信息
appoint = new HmcsAppoint();
BeanUtils.copyProperties(appointmentParam, appoint);
appoint.setBookStartTime(parse);
appoint.setBookEndTime(DateUtil.offsetMinute(parse, 12));
appoint.setStatus(AppointStatus.RESERVED.getType());
appoint.setPayStatus(PayStatus.UNPAID.getStatus());
appoint.setIsUpdated(0);
this.insert(appoint);
//判断预约是否附带文件
if (!CollectionUtils.isEmpty(appointmentParam.getDocuments())) {
//新增预约-文件关系
appointEnclosureService.insertDocuments(appointmentParam.getDocuments(), appoint.getId());
}
//新增一条预约订单
JsonResult result = serverOrderService.insertAppointOrder(appoint, appointmentParam.getPaymentMethod());
return result;
//获取锁失败
} else {
return JsonResult.getFailJsonResult("该时间段已被预约");
}
} catch (InterruptedException e) {
return JsonResult.getFailJsonResult("预约失败");
} finally {
if (getLock){
lock.unlock();
}
}