赞
踩
联锁(RedissonMultiLock)对象可以将多个RLock对象关联为一个联锁,实现加锁和解锁功能。每个RLock对象实例可以来自于不同的Redisson实例。
如果负责储存分布式锁的某些Redis节点宕机以后,而且这些锁正好处于锁住状态,就会出现死锁问题。为了避免这种情况的发生,Redisson内部提供了一个监控锁的看门狗。看门狗的作用是在Redisson实例被关闭前,不断延长锁的有效期。默认情况下,看门狗的检查锁的超时时间是30秒,也可以通过修改Config.lockWatchdogTimeout来另行指定。
我是在Springboot项目中使用的Redisson分布式锁。
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.14.1</version>
</dependency>
server.port=8083 ## master 数据源配置 master.datasource.url=jdbc:mysql://10.5.146.156:3306/USDP?useUnicode=true&characterEncoding=utf8 master.datasource.username=root master.datasource.password=click1 master.datasource.driverClassName=com.mysql.jdbc.Driver # 连接池的配置信息 spring.datasource.type=com.alibaba.druid.pool.DruidDataSource # 初始化大小:建立物理连接的个数 spring.datasource.initialSize=5 # 最小连接数 spring.datasource.minIdle=5 # 最大连接数 spring.datasource.maxActive=20 # 配置获取连接等待超时的时间 spring.datasource.maxWait=60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 spring.datasource.timeBetweenEvictionRunsMillis=60000 # 配置一个连接在池中最小生存的时间,单位是毫秒 spring.datasource.minEvictableIdleTimeMillis=300000 # 用来检测连接是否有效的sql,要求是一个查询语句,常用select 'x'。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用 spring.datasource.validationQuery=SELECT 1 FROM DUAL spring.datasource.testWhileIdle=true spring.datasource.testOnBorrow=false spring.datasource.testOnReturn=false # 打开PSCache,并且指定每个连接上PSCache的大小; # 是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭 spring.datasource.poolPreparedStatements=false spring.datasource.maxPoolPreparedStatementPerConnectionSize=20 # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙; # 属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有:监控统计用的filter:stat, 日志用的filter:log4j, 防御sql注入的filter:wall spring.datasource.filters=stat,wall,log4j # 通过connectProperties属性来打开mergeSql功能;慢SQL记录 spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 ## 打印SQL语句 ##SpringBoot默认是使用info级别,没有指定级别的就用Springboot默认规定的级别:root级别 logging.level.com.test=INFO #该属性用来配置日志文件名,如果该属性不配置,默认文件名为spring.log logging.file=/opt/applog/interfaceautotestagent/test.log #logging.file=/var/log/test.log logging.pattern.console=%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n #指定文件中日志的输出格式 logging.pattern.file=%msg%n # REDIS # Redis数据库索引(默认为0) spring.redis.database=0 ## Redis服务器地址 #spring.redis.host=10.237.78.40 ## Redis服务器连接端口 #spring.redis.port=6379 ## Redis服务器连接密码(默认为空) #spring.redis.password= # 连接池最大连接数(使用负值表示没有限制) spring.redis.lettuce.pool.max-active=16 # 连接池最大阻塞等待时间(使用负值表示没有限制) spring.redis.lettuce.pool.max-wait=-1 # 连接池中的最大空闲连接 spring.redis.lettuce.pool.max-idle=8 # 连接池中的最小空闲连接 spring.redis.lettuce.pool.min-idle=0 # 连接超时时间(毫秒)spring boot 1.x,redisson新加的 spring.redis.timeout=60000 # 执行命令超时时间,单位毫秒 spring.redis.command-timeout: 15000 # 是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个 spring.redis.test-on-borrow: true # 集群模式下,逗号分隔的键值对(主机:端口)形式的服务器列表 #spirng.redis.cluster.nodes=10.237.79.150:6379,10.237.79.150:6380,10.237.79.151:6379,10.237.79.151:6380,10.237.79.152:6379,10.237.79.152:6380 spirng.redis.cluster.nodes=172.24.83.165:6379,172.24.83.165:6380,172.24.83.165:6381,172.24.83.165:6382,172.24.83.165:6383,172.24.83.165:6384 # 集群模式下,集群最大转发的数量 spring.redis.cluster.max-redirects=3 # 最大的连接重试次数 spring.redis.cluster.max-attempts=5 #activemq spring.activemq.broker-url=tcp://10.237.78.6:61616 spring.activemq.user= spring.activemq.password= #spring.activemq.in-memory=true #spring.activemq.pool.enabled=false #使用发布/订阅模式时,下边配置需要设置成 true 是否使用默认的destination type来支持 publish/subscribe,默认: false spring.jms.pub-sub-domain=true ##指定最小的并发消费者数量 #spring.jms.listener.concurrency = 10 ##指定最大的并发消费者数量 #spring.jms.listener.max-concurrency = 10
package com.test.config; import lombok.Data; import org.redisson.config.Config; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import org.springframework.stereotype.Component; import java.util.List; @Data @Component @PropertySource("classpath:application.properties") public class RedisConfigProperties { @Value("${spirng.redis.cluster.nodes}") private String redisClusterNodes; }
package com.test.config; import org.redisson.Redisson; import org.redisson.api.RedissonClient; import org.redisson.config.ClusterServersConfig; import org.redisson.config.Config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.ArrayList; import java.util.List; @Configuration public class RedissonConfig { @Autowired private RedisConfigProperties redisConfigProperties; @Bean public RedissonClient redissonClient1() { //redisson版本是3.5,集群的ip前面要加上“redis://”,不然会报错,3.2版本可不加 List<String> clusterNodes = new ArrayList<>(); for (int i = 0; i < 2; i++) { clusterNodes.add("redis://" + redisConfigProperties.getRedisClusterNodes().split(",")[i]); } Config config = new Config(); // 添加集群地址 ClusterServersConfig clusterServersConfig = config.useClusterServers().addNodeAddress(clusterNodes.toArray(new String[clusterNodes.size()])); // // 设置密码 // clusterServersConfig.setPassword(redisConfigProperties.getPassword()); RedissonClient redissonClient = Redisson.create(config); return redissonClient; } @Bean public RedissonClient redissonClient2() { //redisson版本是3.5,集群的ip前面要加上“redis://”,不然会报错,3.2版本可不加 List<String> clusterNodes = new ArrayList<>(); for (int i = 2; i < 4; i++) { clusterNodes.add("redis://" + redisConfigProperties.getRedisClusterNodes().split(",")[i]); } Config config = new Config(); // 添加集群地址 ClusterServersConfig clusterServersConfig = config.useClusterServers().addNodeAddress(clusterNodes.toArray(new String[clusterNodes.size()])); // // 设置密码 // clusterServersConfig.setPassword(redisConfigProperties.getPassword()); RedissonClient redissonClient = Redisson.create(config); return redissonClient; } @Bean public RedissonClient redissonClient3() { //redisson版本是3.5,集群的ip前面要加上“redis://”,不然会报错,3.2版本可不加 List<String> clusterNodes = new ArrayList<>(); for (int i = 4; i < 5; i++) { clusterNodes.add("redis://" + redisConfigProperties.getRedisClusterNodes().split(",")[i]); } Config config = new Config(); // 添加集群地址 ClusterServersConfig clusterServersConfig = config.useClusterServers().addNodeAddress(clusterNodes.toArray(new String[clusterNodes.size()])); // // 设置密码 // clusterServersConfig.setPassword(redisConfigProperties.getPassword()); RedissonClient redissonClient = Redisson.create(config); return redissonClient; } }
RLock lock1 = redissonClient1.getLock("lock1");
RLock lock2 = redissonClient2.getLock("lock2");
RLock lock3 = redissonClient3.getLock("lock3");
RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3);
// 同时加锁:lock1 lock2 lock3
// 所有的锁都上锁成功才算成功。
lock.lock();
...
lock.unlock();
或
RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3);
// 给lock1,lock2,lock3加锁,如果没有手动解开的话,(leaseTime=10s)10秒钟后将会自动解开
lock.lock(10, TimeUnit.SECONDS);
// 为加锁等待(waitTime=100s)100秒时间,并在加锁成功10秒钟后自动解开
boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
...
lock.unlock();
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。