當前位置:
首頁 >
前端技术
> javascript
>内容正文
javascript
SpringBoot集成Redission实现分布式缓存
生活随笔
收集整理的這篇文章主要介紹了
SpringBoot集成Redission实现分布式缓存
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
github地址:https://github.com/redisson/redisson
一.源碼分析
trylock
tryAcquire
針對過期時間做不同的轉發處理
tryLockInnerAsync
? ?<T> RFuture<T> tryLockInnerAsync(long leaseTime, TimeUnit unit, long threadId, RedisStrictCommand<T> command) {this.internalLockLeaseTime = unit.toMillis(leaseTime);return this.commandExecutor.evalWriteAsync(this.getName(), LongCodec.INSTANCE, command, "if (redis.call('exists', KEYS[1]) == 0) then redis.call('hset', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then redis.call('hincrby', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; return redis.call('pttl', KEYS[1]);", Collections.singletonList(this.getName()), new Object[]{this.internalLockLeaseTime, this.getLockName(threadId)});}通過lua腳本來實現加鎖的操作
判斷lock鍵是否存在,不存在直接調用hset存儲當前線程信息并且設置過期時間,返回nil,告訴客戶端直接獲取到鎖。
判斷lock鍵是否存在,存在則將重入次數加1,并重新設置過期時間,返回nil,告訴客戶端直接獲取到鎖。
被其它線程已經鎖定,返回鎖有效期的剩余時間,告訴客戶端需要等待。
unlock
? ?protected RFuture<Boolean> unlockInnerAsync(long threadId) {return this.commandExecutor.evalWriteAsync(this.getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN, "if (redis.call('hexists', KEYS[1], ARGV[3]) == 0) then return nil;end; local counter = redis.call('hincrby', KEYS[1], ARGV[3], -1); if (counter > 0) then redis.call('pexpire', KEYS[1], ARGV[2]); return 0; else redis.call('del', KEYS[1]); redis.call('publish', KEYS[2], ARGV[1]); return 1; end; return nil;", Arrays.asList(this.getName(), this.getChannelName()), new Object[]{LockPubSub.UNLOCK_MESSAGE, this.internalLockLeaseTime, this.getLockName(threadId)});}
如果lock鍵不存在,發消息說鎖已經可用,發送一個消息
如果鎖不是被當前線程鎖定,則返回nil
由于支持可重入,在解鎖時將重入次數需要減1
如果計算后的重入次數>0,則重新設置過期時間
如果計算后的重入次數<=0,則發消息說鎖已經可用
二.在SpringBoot中的使用
1.pom依賴
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.8.1</version></dependency><dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.11.5</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>2.Lock接口
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); }3.Lock接口實現類
public class RedissonDistributedLocker implements DistributedLocker { ?private RedissonClient redissonClient; ? ?public void setRedissonClient(RedissonClient redissonClient) {this.redissonClient = redissonClient;} ?@Overridepublic RLock lock(String lockKey) {RLock lock = redissonClient.getLock(lockKey);lock.lock();return lock;} ?@Overridepublic RLock lock(String lockKey, int leaseTime) {RLock lock = redissonClient.getLock(lockKey);lock.lock(leaseTime, TimeUnit.SECONDS);return lock;} ?@Overridepublic RLock lock(String lockKey, TimeUnit unit, int timeout) {RLock lock = redissonClient.getLock(lockKey);lock.lock(timeout, unit);return lock;} ?@Overridepublic 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;}} ?@Overridepublic void unlock(String lockKey) {RLock lock = redissonClient.getLock(lockKey);lock.unlock();} ?@Overridepublic void unlock(RLock lock) {lock.unlock();} }4.RedissLock工具類
public class RedissLockUtil {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);} }5.屬性裝配類
@Configuration @ConfigurationProperties(prefix = "redisson") @ConditionalOnProperty("redisson.password") @Data public 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; }6.SpringBoot自動裝配類
@Configuration @ConditionalOnClass(Config.class) @EnableConfigurationProperties(RedissonProperties.class) public class RedissonAutoConfiguration { ?@Autowiredprivate 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類,并將實例注入到RedissionLockUtil中** @return*/@BeanDistributedLocker distributedLocker(RedissonClient redissonClient) {RedissonDistributedLocker locker = new RedissonDistributedLocker();locker.setRedissonClient(redissonClient);RedissLockUtil.setLocker(locker);return locker;} }7.配置文件
redisson:address: redis://localhost:6379password:#哨兵模式的配置#sentinel-addresses: xxx.xxx.xxx.xxx:port,xxx.xxx.xxx.xxx:port8.加鎖測試
? ?@GetMapping("/test")public String testRedission() {CountDownLatch countDownLatch = new CountDownLatch(10); ?for (int i = 0; i < 10; i++) {new Thread(() -> {try {countDownLatch.await();} catch (InterruptedException e) {e.printStackTrace();}RedissLockUtil.lock("test");for (int j = 0; j < 100; j++) {System.out.println(Thread.currentThread() + "---" + j);try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}} ?RedissLockUtil.unlock("test");}).start();countDownLatch.countDown();} ?return "success";}總結
以上是生活随笔為你收集整理的SpringBoot集成Redission实现分布式缓存的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Zookeeper之Leader选举源码
- 下一篇: SpringBoot之使用RabbitM