赞
踩
本文主要描述springboot继承redisson的几种方式以及redisson分布式锁的使用;
Redisson是架设在Redis基础上的一个Java驻内存数据网格(In-Memory Data Grid)。
Redisson在基于NIO的Netty框架上,充分的利用了Redis键值数据库提供的一系列优势,在Java实用工具包中常用接口的基础上,为使用者提供了一系列具有分布式特性的常用工具类。使得原本作为协调单机多线程并发程序的工具包获得了协调分布式多机多线程并发系统的能力,大大降低了设计和研发大规模分布式系统的难度。同时结合各富特色的分布式服务,更进一步简化了分布式环境中程序相互之间的协作。
最熟为人知的是它的分布式锁机制,它有比redis本身更多更强劲的功能
- 分布式锁原理 : 发送一段lua脚本(保证原子性)用以加锁,其本质是抢占key,谁先生成key谁就有锁
- 以后再补一篇原理
redisson 集成springBoot并不是特别友好,因为它没有像redis这样写自动配置类,故不能仅写配置就能用
引入pom坐标:
- <!--分布式锁-->
- <dependency>
- <groupId>org.redisson</groupId>
- <artifactId>redisson</artifactId>
- <version>3.13.6</version>
- </dependency>
要点:
1.自己写配置属性
2.自己写@Bean注入redisson
配置类
- import com.xkj.ecommerce.utils.RedissonLockUtil;
- import lombok.Data;
- 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.boot.autoconfigure.AutoConfigureOrder;
- import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
- import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
- import org.springframework.boot.context.properties.ConfigurationProperties;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
-
- import java.util.Arrays;
-
- /**
- * @createDate 2021/1/18
- */
- @Configuration
- @ConfigurationProperties(prefix = "redisson")
- @Data
- @AutoConfigureOrder
- public class RedissonConfig {
-
- 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;
-
- public void setSentinelAddresses(String sentinelAddresses) {
- this.sentinelAddresses = Arrays.stream(sentinelAddresses.split(",")).map(s -> "redis://" + s).toArray(String[]::new);
- }
-
- public void setAddress(String address) {
- this.address = "redis://" + address;
- }
-
-
- /**
- * 哨兵模式自动装配
- */
- @Bean
- @ConditionalOnMissingBean(RedissonClient.class)
- @ConditionalOnProperty(name = "redisson.masterName")
- public RedissonLockUtil redissonSentinel() {
- Config config = new Config();
- SentinelServersConfig serverConfig = config.useSentinelServers().addSentinelAddress(this.getSentinelAddresses())
- .setMasterName(this.getMasterName())
- .setTimeout(this.getTimeout())
- .setMasterConnectionPoolSize(this.getMasterConnectionPoolSize())
- .setSlaveConnectionPoolSize(this.getSlaveConnectionPoolSize());
-
- if (StringUtils.isNotBlank(this.getPassword())) {
- serverConfig.setPassword(this.getPassword());
- }
- RedissonClient redissonClient = Redisson.create(config);
- RedissonLockUtil locker = new RedissonLockUtil();
- locker.setRedissonClient(redissonClient);
- return locker;
- }
-
- /**
- * 单机模式自动装配
- */
- @Bean
- @ConditionalOnProperty(name = "redisson.address")
- public RedissonLockUtil redissonSingle() {
- Config config = new Config();
-
- SingleServerConfig serverConfig = config.useSingleServer()
- .setAddress(this.getAddress())
- .setTimeout(this.getTimeout())
- .setConnectionPoolSize(this.getConnectionPoolSize())
- .setConnectionMinimumIdleSize(this.getConnectionMinimumIdleSize());
-
- if (StringUtils.isNotBlank(this.getPassword())) {
- serverConfig.setPassword(this.getPassword());
- }
- RedissonClient redissonClient = Redisson.create(config);
- RedissonLockUtil locker = new RedissonLockUtil();
- locker.setRedissonClient(redissonClient);
- return locker;
- }
-
- }
- redisson.timeout=3000
- ....
- # 哨兵配置(用英文逗号隔开)
- # redisson.sentinelAddresses=192.168.2.100:3408,192.168.2.101:3408
- # 单机配置
- redisson.address=192.168.2.100:3408
要点:
1.使用redisson官方提供的工具类,读取指定配置项
配置类
- import org.redisson.Redisson;
- import org.redisson.api.RedissonClient;
- import org.redisson.config.Config;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
-
- import java.io.IOException;
-
- @Configuration
- public class RedissonConfig {
-
- @Bean
- public RedissonClient redisson() throws IOException {
- // 本例子使用的是yaml格式的配置文件,读取使用Config.fromYAML,如果是Json文件,则使用Config.fromJSON
- Config config = Config.fromYAML(RedissonConfig.class.getClassLoader().getResource("redisson-config.yml"));
- return Redisson.create(config);
- }
- }
自行注入到工具类中,参考
RedissonClient redissonClient = Redisson.create(config);
RedissonLockUtil locker = new RedissonLockUtil(); locker.setRedissonClient(redissonClient);
redisson-config.yml
- #Redisson配置
- singleServerConfig:
- address: "redis://127.0.0.1:6379"
- password: null
- clientName: null
- database: 7 #选择使用哪个数据库0~15
- idleConnectionTimeout: 10000
- pingTimeout: 1000
- connectTimeout: 10000
- timeout: 3000
- retryAttempts: 3
- retryInterval: 1500
- reconnectionTimeout: 3000
- failedAttempts: 3
- subscriptionsPerConnection: 5
- subscriptionConnectionMinimumIdleSize: 1
- subscriptionConnectionPoolSize: 50
- connectionMinimumIdleSize: 32
- connectionPoolSize: 64
- dnsMonitoringInterval: 5000
- #dnsMonitoring: false
-
- threads: 0
- nettyThreads: 0
- codec:
- class: "org.redisson.codec.JsonJacksonCodec"
- transportMode: "NIO"
引入springboot-redisson坐标
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-redis</artifactId>
- </dependency>
- <!-- https://mvnrepository.com/artifact/org.redisson/redisson-spring-boot-starter -->
- <dependency>
- <groupId>org.redisson</groupId>
- <artifactId>redisson-spring-boot-starter</artifactId>
- <version>3.12.0</version>
- </dependency>
与yaml方式类似,应该属于进阶版
application.yml
# 公共的spring配置 spring.redis.database= spring.redis.host= spring.redis.port= spring.redis.password= spring.redis.ssl= spring.redis.timeout= spring.redis.cluster.nodes= spring.redis.sentinel.master= spring.redis.sentinel.nodes= # Redisson 的特殊配置 # 可以从本地的类路径下读取配置文件 spring.redis.redisson.config=classpath:redisson-config.yml
然后可以直接使用
- @Autowired
- RedissonClient redissonClient;
- import org.redisson.api.RLock;
- import org.redisson.api.RedissonClient;
-
- import java.util.concurrent.TimeUnit;
-
- public class RedissonLockUtil {
-
- private static RedissonClient redissonClient;
-
- public void setRedissonClient(RedissonClient redissonCli) {
- redissonClient = redissonCli;
- }
-
-
- public static RLock lock(String lockKey) {
- RLock lock = redissonClient.getLock(lockKey);
- lock.lock();
- return lock;
- }
-
- public static RLock lock(String lockKey, int leaseTime) {
- RLock lock = redissonClient.getLock(lockKey);
- lock.lock(leaseTime, TimeUnit.SECONDS);
- return lock;
- }
-
- public static RLock lock(String lockKey, TimeUnit unit, int timeout) {
- RLock lock = redissonClient.getLock(lockKey);
- lock.lock(timeout, unit);
- return lock;
- }
-
- /**
- * 尝试获得锁,自定义 时间单位;等待时长;加锁时长
- */
- public static boolean tryLock(String lockKey, int waitTime, int leaseTime, TimeUnit unit) {
- RLock lock = redissonClient.getLock(lockKey);
- try {
- return lock.tryLock(waitTime, leaseTime, unit);
- } catch (InterruptedException e) {
- return false;
- }
- }
-
-
- /**
- * 尝试获得锁,自定义 等待时长;加锁时长 (默认为秒)
- */
- public static boolean tryLock(String lockKey, int waitTime, int leaseTime) {
- RLock lock = redissonClient.getLock(lockKey);
- try {
- return lock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS);
- } catch (InterruptedException e) {
- return false;
- }
- }
-
- /**
- * 尝试获得锁,自定义 等待时长 (加锁时长不限制;默认为秒)
- */
- public static boolean tryLock(String lockKey, int waitTime) {
- RLock lock = redissonClient.getLock(lockKey);
- try {
- return lock.tryLock(waitTime, TimeUnit.SECONDS);
- } catch (InterruptedException e) {
- return false;
- }
- }
-
- /**
- * 尝试获得锁,自定义 等待时长 (加锁时长不限制)
- */
- public static boolean tryLock(String lockKey, int waitTime, TimeUnit unit) {
- RLock lock = redissonClient.getLock(lockKey);
- try {
- return lock.tryLock(waitTime, unit);
- } catch (InterruptedException e) {
- return false;
- }
- }
-
- public static void unlock(String lockKey) {
- RLock lock = redissonClient.getLock(lockKey);
- lock.unlock();
- }
-
- public static void unlock(RLock lock) {
- lock.unlock();
- }
- }
用的时候就可以直接 RedissonLockUtil.lock("test")
(据说redisson和redisson-spring-boot-starter用的不是同一套体系,如果考虑引包的兼容性,建议用第三种方式)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。