Springboot与Redisson整合教程:轻松实现分布式锁之七
最编程
2024-07-28 17:59:25
...
前言
该篇是基于springboot 项目整合 Redisson 实现对redis的操作。
内容:
1.以自定注解aop方式实现对接口使用分布式锁
2.使用RedissonClient对一些集合的常规操作,数据查询,存储等
正文
第一步:
pom.xml 添加核心依赖包:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <!--使用Redis--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.9.1</version> </dependency>
第二步:
新建RedissonConfig.java:
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; /** * redisson bean管理 */ @Configuration public class RedissonConfig { /** * Redisson客户端注册 * 单机模式 */ @Bean(destroyMethod = "shutdown") public RedissonClient createRedissonClient() throws IOException { // Config config = new Config(); // SingleServerConfig singleServerConfig = config.useSingleServer(); // singleServerConfig.setAddress("redis://127.0.0.1:6379"); // singleServerConfig.setPassword("12345"); // singleServerConfig.setTimeout(3000); // return Redisson.create(config) // 本例子使用的是yaml格式的配置文件,读取使用Config.fromYAML,如果是Json文件,则使用Config.fromJSON Config config = Config.fromYAML(RedissonConfig.class.getClassLoader().getResource("redisson-config.yml")); return Redisson.create(config); } /** * 主从模式 哨兵模式 * **/ /* @Bean public RedissonClient getRedisson() { RedissonClient redisson; Config config = new Config(); config.useMasterSlaveServers() //可以用"rediss://"来启用SSL连接 .setMasterAddress("redis://***(主服务器IP):6379").setPassword("web2017") .addSlaveAddress("redis://***(从服务器IP):6379") .setReconnectionTimeout(10000) .setRetryInterval(5000) .setTimeout(10000) .setConnectTimeout(10000);//(连接超时,单位:毫秒 默认值:3000); // 哨兵模式config.useSentinelServers().setMasterName("mymaster").setPassword("web2017").addSentinelAddress("***(哨兵IP):26379", "***(哨兵IP):26379", "***(哨兵IP):26380"); redisson = Redisson.create(config); return redisson; }*/ }
上面配置里可以使用传值方式去连接redis,也可以选择从配置文件获取参数,反正方式多样。
redisson-config.yml 文件(如果没有密码设置为null即可):
#Redisson配置 singleServerConfig: address: "redis://127.0.0.1:6379" password: 12345 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"
第三步:
使用锁,新建DistributeLocker.java :
import java.util.concurrent.TimeUnit; /** * @Author : JCccc * @CreateTime : 2020/5/13 * @Description : **/ public interface DistributeLocker { /** * 加锁 * @param lockKey key */ void lock(String lockKey); /** * 释放锁 * * @param lockKey key */ void unlock(String lockKey); /** * 加锁锁,设置有效期 * * @param lockKey key * @param timeout 有效时间,默认时间单位在实现类传入 */ void lock(String lockKey, int timeout); /** * 加锁,设置有效期并指定时间单位 * @param lockKey key * @param timeout 有效时间 * @param unit 时间单位 */ void lock(String lockKey, int timeout, TimeUnit unit); /** * 尝试获取锁,获取到则持有该锁返回true,未获取到立即返回false * @param lockKey * @return true-获取锁成功 false-获取锁失败 */ boolean tryLock(String lockKey); /** * 尝试获取锁,获取到则持有该锁leaseTime时间. * 若未获取到,在waitTime时间内一直尝试获取,超过waitTime还未获取到则返回false * @param lockKey key * @param waitTime 尝试获取时间 * @param leaseTime 锁持有时间 * @param unit 时间单位 * @return true-获取锁成功 false-获取锁失败 */ boolean tryLock(String lockKey, long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException; /** * 锁是否被任意一个线程锁持有 * @param lockKey * @return true-被锁 false-未被锁 */ boolean isLocked(String lockKey); //lock.isHeldByCurrentThread()的作用是查询当前线程是否保持此锁定 boolean isHeldByCurrentThread(String lockKey); }
再是新建这个锁接口的实现类 ,RedissonDistributeLocker.java :
import org.redisson.api.RLock; import org.redisson.api.RedissonClient; import java.util.concurrent.TimeUnit; /** * redisson实现分布式锁接口 */ public class RedissonDistributeLocker implements DistributeLocker { private RedissonClient redissonClient; public RedissonDistributeLocker(RedissonClient redissonClient) { this.redissonClient = redissonClient; } @Override public void lock(String lockKey) { RLock lock = redissonClient.getLock(lockKey); lock.lock(); } @Override public void unlock(String lockKey) { RLock lock = redissonClient.getLock(lockKey); lock.unlock(); } @Override public void lock(String lockKey, int leaseTime) { RLock lock = redissonClient.getLock(lockKey); lock.lock(leaseTime, TimeUnit.MILLISECONDS); } @Override public void lock(String lockKey, int timeout, TimeUnit unit) { RLock lock = redissonClient.getLock(lockKey); lock.lock(timeout, unit); } @Override public boolean tryLock(String lockKey) { RLock lock = redissonClient.getLock(lockKey); return lock.tryLock(); } @Override public boolean tryLock(String lockKey, long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException { RLock lock = redissonClient.getLock(lockKey); return lock.tryLock(waitTime, leaseTime, unit); } @Override public boolean isLocked(String lockKey) { RLock lock = redissonClient.getLock(lockKey); return lock.isLocked(); } @Override public boolean isHeldByCurrentThread(String lockKey) { RLock lock = redissonClient.getLock(lockKey); return lock.isHeldByCurrentThread(); } }
然后新建锁操作工具类,RedissonLockUtils.java :