SpringBoot中怎么利用Redisson实现分布式锁
创始人
2024-12-23 01:43:03
0次

导入依赖

org.redissonredisson3.8.0

属性配置

在 application.properites 资源文件中添加单机&哨兵相关配置

server.port=3000# redisson lock 单机模式redisson.address=redis://127.0.0.1:6379redisson.password=#哨兵模式#redisson.master-name= master#redisson.password=#redisson.sentinel-addresses=10.47.91.83:26379,10.47.91.83:26380,10.47.91.83:26381

注意:

这里如果不加 redis:// 前缀会报 URI 构建错误

Caused by: java.net.URISyntaxException: Illegal character in scheme name at index 0

更多的配置信息可以去官网查看

定义Lock的接口定义类

package com.tuhu.thirdsample.service;import org.redisson.api.RLock;import java.util.concurrent.TimeUnit;/** * @author chendesheng * @create 2019/10/12 10:48 */public interface DistributedLocker { RLock lock(String lockKey); RLock lock(String lockKey, int timeout); RLock lock(String lockKey, TimeUnit unit, int timeout); boolean tryLock(String lockKey, TimeUnit unit, int waitTime, int leaseTime); void unlock(String lockKey); void unlock(RLock lock);}

Lock接口实现类

package com.tuhu.thirdsample.service;import org.redisson.api.RLock;import org.redisson.api.RedissonClient;import java.util.concurrent.TimeUnit;/** * @author chendesheng * @create 2019/10/12 10:49 */public class RedissonDistributedLocker implements DistributedLocker{ private RedissonClient redissonClient; @Override public RLock lock(String lockKey) {  RLock lock = redissonClient.getLock(lockKey);  lock.lock();  return lock; } @Override public RLock lock(String lockKey, int leaseTime) {  RLock lock = redissonClient.getLock(lockKey);  lock.lock(leaseTime, TimeUnit.SECONDS);  return lock; } @Override public RLock lock(String lockKey, TimeUnit unit ,int timeout) {  RLock lock = redissonClient.getLock(lockKey);  lock.lock(timeout, unit);  return lock; } @Override public boolean tryLock(String lockKey, TimeUnit unit, int waitTime, int leaseTime) {  RLock lock = redissonClient.getLock(lockKey);  try {   return lock.tryLock(waitTime, leaseTime, unit);  } catch (InterruptedException e) {   return false;  } } @Override public void unlock(String lockKey) {  RLock lock = redissonClient.getLock(lockKey);  lock.unlock(); } @Override public void unlock(RLock lock) {  lock.unlock(); } public void setRedissonClient(RedissonClient redissonClient) {  this.redissonClient = redissonClient; }}

redisson属性装配类

package com.tuhu.thirdsample.common;import lombok.Data;import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.context.annotation.Configuration;/** * @author chendesheng * @create 2019/10/11 20:04 */@Configuration@ConfigurationProperties(prefix = "redisson")@ConditionalOnProperty("redisson.password")@Datapublic class RedissonProperties { private int timeout = 3000; private String address; private String password; private int database = 0; private int connectionPoolSize = 64; private int connectionMinimumIdleSize=10; private int slaveConnectionPoolSize = 250; private int masterConnectionPoolSize = 250; private String[] sentinelAddresses; private String masterName;}

SpringBoot自动装配类

package com.tuhu.thirdsample.configuration;import com.tuhu.thirdsample.common.RedissonProperties;import com.tuhu.thirdsample.service.DistributedLocker;import com.tuhu.thirdsample.service.RedissonDistributedLocker;import com.tuhu.thirdsample.util.RedissonLockUtil;import org.apache.commons.lang3.StringUtils;import org.redisson.Redisson;import org.redisson.api.RedissonClient;import org.redisson.config.Config;import org.redisson.config.SentinelServersConfig;import org.redisson.config.SingleServerConfig;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;import org.springframework.boot.context.properties.EnableConfigurationProperties;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/** * @author chendesheng * @create 2019/10/12 10:50 */@Configuration@ConditionalOnClass(Config.class)@EnableConfigurationProperties(RedissonProperties.class)public class RedissonAutoConfiguration { @Autowired private RedissonProperties redissonProperties; /**  * 哨兵模式自动装配  * @return  */ @Bean @ConditionalOnProperty(name="redisson.master-name") RedissonClient redissonSentinel() {  Config config = new Config();  SentinelServersConfig serverConfig = config.useSentinelServers().addSentinelAddress(redissonProperties.getSentinelAddresses())    .setMasterName(redissonProperties.getMasterName())    .setTimeout(redissonProperties.getTimeout())    .setMasterConnectionPoolSize(redissonProperties.getMasterConnectionPoolSize())    .setSlaveConnectionPoolSize(redissonProperties.getSlaveConnectionPoolSize());  if(StringUtils.isNotBlank(redissonProperties.getPassword())) {   serverConfig.setPassword(redissonProperties.getPassword());  }  return Redisson.create(config); } /**  * 单机模式自动装配  * @return  */ @Bean @ConditionalOnProperty(name="redisson.address") RedissonClient redissonSingle() {  Config config = new Config();  SingleServerConfig serverConfig = config.useSingleServer()    .setAddress(redissonProperties.getAddress())    .setTimeout(redissonProperties.getTimeout())    .setConnectionPoolSize(redissonProperties.getConnectionPoolSize())    .setConnectionMinimumIdleSize(redissonProperties.getConnectionMinimumIdleSize());  if(StringUtils.isNotBlank(redissonProperties.getPassword())) {   serverConfig.setPassword(redissonProperties.getPassword());  }  return Redisson.create(config); } /**  * 装配locker类,并将实例注入到RedissLockUtil中  * @return  */ @Bean DistributedLocker distributedLocker(RedissonClient redissonClient) {  DistributedLocker locker = new RedissonDistributedLocker();  ((RedissonDistributedLocker) locker).setRedissonClient(redissonClient);  RedissonLockUtil.setLocker(locker);  return locker; }}

Lock帮助类

package com.tuhu.thirdsample.util;import com.tuhu.thirdsample.service.DistributedLocker;import org.redisson.api.RLock;import java.util.concurrent.TimeUnit;/** * @author chendesheng * @create 2019/10/12 10:54 */public class RedissonLockUtil { private static DistributedLocker redissLock; public static void setLocker(DistributedLocker locker) {  redissLock = locker; } /**  * 加锁  * @param lockKey  * @return  */ public static RLock lock(String lockKey) {  return redissLock.lock(lockKey); } /**  * 释放锁  * @param lockKey  */ public static void unlock(String lockKey) {  redissLock.unlock(lockKey); } /**  * 释放锁  * @param lock  */ public static void unlock(RLock lock) {  redissLock.unlock(lock); } /**  * 带超时的锁  * @param lockKey  * @param timeout 超时时间 单位:秒  */ public static RLock lock(String lockKey, int timeout) {  return redissLock.lock(lockKey, timeout); } /**  * 带超时的锁  * @param lockKey  * @param unit 时间单位  * @param timeout 超时时间  */ public static RLock lock(String lockKey, TimeUnit unit , int timeout) {  return redissLock.lock(lockKey, unit, timeout); } /**  * 尝试获取锁  * @param lockKey  * @param waitTime 最多等待时间  * @param leaseTime 上锁后自动释放锁时间  * @return  */ public static boolean tryLock(String lockKey, int waitTime, int leaseTime) {  return redissLock.tryLock(lockKey, TimeUnit.SECONDS, waitTime, leaseTime); } /**  * 尝试获取锁  * @param lockKey  * @param unit 时间单位  * @param waitTime 最多等待时间  * @param leaseTime 上锁后自动释放锁时间  * @return  */ public static boolean tryLock(String lockKey, TimeUnit unit, int waitTime, int leaseTime) {  return redissLock.tryLock(lockKey, unit, waitTime, leaseTime); }}

控制层

package com.tuhu.thirdsample.task;import com.tuhu.thirdsample.common.KeyConst;import lombok.extern.slf4j.Slf4j;import org.redisson.api.RLock;import org.redisson.api.RedissonClient;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import java.util.concurrent.TimeUnit;/** * @author chendesheng * @create 2019/10/12 11:03 */@RestController@RequestMapping("/lock")@Slf4jpublic class LockController { @Autowired RedissonClient redissonClient;  @GetMapping("/task") public void task(){  log.info("task start");  RLock lock = redissonClient.getLock(KeyConst.REDIS_LOCK_KEY);  boolean getLock = false;  try {   if (getLock = lock.tryLock(0,5,TimeUnit.SECONDS)){    //执行业务逻辑    System.out.println("拿到锁干活");   }else {    log.info("Redisson分布式锁没有获得锁:{},ThreadName:{}",KeyConst.REDIS_LOCK_KEY,Thread.currentThread().getName());   }  } catch (InterruptedException e) {   log.error("Redisson 获取分布式锁异常,异常信息:{}",e);  }finally {   if (!getLock){    return;   }   //如果演示的话需要注释该代码;实际应该放开   //lock.unlock();   //log.info("Redisson分布式锁释放锁:{},ThreadName :{}", KeyConst.REDIS_LOCK_KEY, Thread.currentThread().getName());  } }}

RLock 继承自 java.util.concurrent.locks.Lock ,可以将其理解为一个重入锁,需要手动加锁和释放锁 。

来看它其中的一个方法:tryLock(long waitTime, long leaseTime, TimeUnit unit)

getLock = lock.tryLock(0,5,TimeUnit.SECONDS)

通过 tryLock() 的参数可以看出,在获取该锁时如果被其他线程先拿到锁就会进入等待,等待 waitTime 时间,如果还没用机会获取到锁就放弃,返回 false;若获得了锁,除非是调用 unlock 释放,那么会一直持有锁,直到超过 leaseTime 指定的时间。

相关内容

热门资讯

空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...