赞
踩
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.3.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.16.4</version>
</dependency>
redisson: server: # 单机:stand-alone host: 101.43.201.38 port: 6379 database: 0 type: stand-alone # 哨兵:sentinel ;主从: 或者 master-slave 集群:cluster # master: mymaster # nodes: 172.16.39.18:26376,172.16.39.18:26377,172.16.39.18:26378 # password: csp172@eb5g # database: 0 # type: sentinel # 集群:cluster # nodes: 172.16.39.18:26376,172.16.39.18:26377,172.16.39.18:26378 # password: csp172@eb5g # database: 0 # type: cluster #获取锁最长等待时间,单位秒 waitTime: 10 #锁过期最长时间,单位秒 leaseTime: 10
package com.microservice.stock.config; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; /** * @author zzkk * @desc redisson配置, * 如需使用, * 请将配置加入到spring容器 ,放开@Component 、 @ConfigurationProperties, * 并在yaml中添加配置 * @date 2022/9/22 10:39 */ @Component @ConfigurationProperties(prefix = "redisson.server") @Data @NoArgsConstructor @AllArgsConstructor public class RedissonProperties { /** * redis主机地址 */ private String host; /** * PORT */ private String port; /** * 连接类型,支持stand-alone-单机节点,sentinel-哨兵,cluster-集群,master-slave-主从 */ private String type; /** * redis 连接密码 */ private String password; /** * 选取那个数据库 */ private String database; /** * 节点信息 */ private String nodes; /** * 主节点 */ private String master; public RedissonProperties setPassword(String password) { this.password = password; return this; } public RedissonProperties setDatabase(String database) { this.database = database; return this; } }
package com.microservice.stock.config; import com.microservice.stock.utils.redisson.StandAlone; import lombok.RequiredArgsConstructor; import org.redisson.api.RedissonClient; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @author zzkk * @desc RedissionConfig * @date 2022/9/22 10:27 */ @Configuration @RequiredArgsConstructor public class RedissonConfig { private final RedissonProperties redissonProperties; @Bean public RedissonClient getRedisson() { return StandAlone.getInstance(redissonProperties); } }
package com.microservice.stock.utils.redisson; import com.microservice.stock.config.RedissonProperties; import org.redisson.Redisson; import org.redisson.api.RedissonClient; import org.redisson.config.Config; import org.redisson.config.SingleServerConfig; import org.springframework.util.StringUtils; /** * @author zzkk * @desc 单机 * @date 2022/9/22 11:06 */ public class StandAlone { public static volatile RedissonClient standAloneClient = null; public static synchronized RedissonClient getInstance(RedissonProperties redissonProperties) { String type = "stand-alone"; if (!type.equalsIgnoreCase(redissonProperties.getType().trim())) { return Sentinel.getInstance(redissonProperties); } //实例没创建,才会进入内部的 synchronized 代码块,提高性能,防止每次都加锁 if (standAloneClient == null) { //可能第一个线程在synchronized 代码块还没创建完对象时,第二个线程已经到了这一步,所以里面还需要加上判断 synchronized (StandAlone.class) { //也许有其他线程已经创建实例,所以再判断一次 if (standAloneClient == null) { Config config = new Config(); SingleServerConfig singleServerConfig = config.useSingleServer() .setAddress("redis://" + redissonProperties.getHost() + ":" + redissonProperties.getPort()); if (StringUtils.hasText(redissonProperties.getPassword())) { singleServerConfig.setPassword(redissonProperties.getPassword()); } if (StringUtils.hasText(redissonProperties.getDatabase())) { singleServerConfig.setDatabase(Integer.parseInt(redissonProperties.getDatabase())); } standAloneClient = Redisson.create(config); } } } return standAloneClient; } }
package com.microservice.stock.utils.redisson; import com.microservice.stock.config.RedissonProperties; import org.redisson.Redisson; import org.redisson.api.RedissonClient; import org.redisson.config.Config; import org.redisson.config.MasterSlaveServersConfig; import org.springframework.util.StringUtils; import java.util.HashSet; import java.util.Set; /** * @author zzkk * @desc 主从 * @date 2022/9/22 14:33 */ public class MasterSlave { public static volatile RedissonClient masterSlaveClient = null; public static synchronized RedissonClient getInstance(RedissonProperties redissonProperties) { String type = "master-slave"; if (!type.equalsIgnoreCase(redissonProperties.getType())) { return Cluster.getInstance(redissonProperties); } if (masterSlaveClient == null) { synchronized (MasterSlave.class) { if (masterSlaveClient == null) { Config config = new Config(); String[] adds = redissonProperties.getNodes().split(","); Set<String> nodeAddress = new HashSet<>(); for (int i = 0; i < adds.length; i++) { StringBuilder stringBuilder = new StringBuilder("redis://"); adds[i] = stringBuilder.append(adds[i]).toString(); nodeAddress.add(adds[i]); } MasterSlaveServersConfig masterSlaveServersConfig = config.useMasterSlaveServers().setMasterAddress(adds[0]); masterSlaveServersConfig.setSlaveAddresses(nodeAddress); if (org.springframework.util.StringUtils.hasText(redissonProperties.getPassword())) { masterSlaveServersConfig.setPassword(redissonProperties.getPassword()); } if (StringUtils.hasText(redissonProperties.getDatabase())) { masterSlaveServersConfig.setDatabase(Integer.parseInt(redissonProperties.getDatabase())); } masterSlaveClient = Redisson.create(config); } } } return masterSlaveClient; } }
package com.microservice.stock.utils.redisson; import com.microservice.stock.config.RedissonProperties; import org.redisson.Redisson; import org.redisson.api.RedissonClient; import org.redisson.config.Config; import org.redisson.config.SentinelServersConfig; import org.springframework.util.StringUtils; /** * @author zzkk * @desc 哨兵 * @date 2022/9/22 11:06 */ public class Sentinel { public static volatile RedissonClient sentinelClient = null; public static synchronized RedissonClient getInstance(RedissonProperties redissonProperties) { String type = "sentinel"; if (!type.equalsIgnoreCase(redissonProperties.getType())) { return Cluster.getInstance(redissonProperties); } if (sentinelClient == null) { synchronized (Sentinel.class) { if (sentinelClient == null) { Config config = new Config(); String[] adds = redissonProperties.getNodes().split(","); for (int i = 0; i < adds.length; i++) { StringBuilder stringBuilder = new StringBuilder("redis://"); adds[i] = stringBuilder.append(adds[i]).toString(); } SentinelServersConfig serverConfig = config.useSentinelServers() .addSentinelAddress(adds) .setMasterName(redissonProperties.getMaster()); if (org.springframework.util.StringUtils.hasText(redissonProperties.getPassword())) { serverConfig.setSentinelPassword(redissonProperties.getPassword()); } if (StringUtils.hasText(redissonProperties.getDatabase())) { serverConfig.setDatabase(Integer.parseInt(redissonProperties.getDatabase())); } sentinelClient = Redisson.create(config); } } } return sentinelClient; } }
package com.microservice.stock.utils.redisson; import com.microservice.stock.config.RedissonProperties; import org.redisson.Redisson; import org.redisson.api.RedissonClient; import org.redisson.config.ClusterServersConfig; import org.redisson.config.Config; import org.springframework.util.StringUtils; /** * @author zzkk * @desc 集群 * @date 2022/9/22 11:06 */ public class Cluster { public static volatile RedissonClient clusterClient = null; public static synchronized RedissonClient getInstance(RedissonProperties redissonProperties) { String type = "cluster"; if (!type.equalsIgnoreCase(redissonProperties.getType().trim())) { return MasterSlave.getInstance(redissonProperties); } if (clusterClient == null) { synchronized (Cluster.class) { if (clusterClient == null) { String[] nodesList = redissonProperties.getNodes().split(","); for (int i = 0; i < nodesList.length; i++) { StringBuilder stringBuilder = new StringBuilder("redis://"); nodesList[i] = stringBuilder.append(nodesList[i]).toString(); } Config config = new Config(); ClusterServersConfig clusterServersConfig = config.useClusterServers().addNodeAddress(nodesList); if (StringUtils.hasText(redissonProperties.getPassword())) { clusterServersConfig.setPassword(redissonProperties.getPassword()); } clusterClient = Redisson.create(config); } } } return clusterClient; } }
@Resource RedissonClient redissonClient; @Test public void redissionTest() throws InterruptedException { StopWatch stopWatch = new StopWatch(); stopWatch.start("redission休眠看门口狗续约测试"); final String lockKey = "my_redission_key"; final RLock lock = redissonClient.getLock(lockKey); if (lock.tryLock()) { try { System.out.println("加锁成功,等待观察redis过期时间是否自动续期"); TimeUnit.SECONDS.sleep(60); System.out.println("休眠结束"); } finally { if (lock.isLocked() && lock.isHeldByCurrentThread()) { System.out.println("释放当前执行线程的锁"); lock.unlock(); } System.out.println("解锁成功"); } } stopWatch.stop(); System.out.println(stopWatch.prettyPrint()); }
// 1、lock.tryLock(2, 40, TimeUnit.SECONDS) 自定义最大加锁时长,看门狗续约会失效;
// 可能发生加锁代码未执行完成,但锁已经过期,出现解锁异常,
// 或者解锁到其他线程加的锁(可以用lock.isHeldByCurrentThread()检查锁是否被当前线程持有);所以不建议使用自定义有效期
// 2、lock.tryLock(),使用看门狗自动续约机制(每隔10秒自动续约,默认30秒)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。