SpringBoot 통합 Redisson 분포 식 잠 금 실현 방법 예시

전편'SpringBoot 통합 redis 분포 식 잠 금 최적화'는 잠 금 해제 문 제 를 최적화 시 켰 다.오늘 은 redis 가 공식 적 으로 추천 하 는 Redisson 을 소개 한다.Redisson 은 redis 를 바탕 으로 하 는 자바 메모리 데이터 그리드(In-memory Data Grid)를 가설 하고 NIO 의 Netty 프레임 워 크 를 바탕 으로 redis 키 데이터 베 이 스 를 이용 했다.기능 이 매우 강해 서 많은 분포 식 구조 중의 문 제 를 해결 했다.
Github 의 wiki 주소:https://github.com/redisson/redisson/wiki
공식 문서:https://github.com/redisson/redisson/wiki/목차
프로젝트 코드 구성 도:
 
가 져 오기 의존

<dependency>
	<groupId>org.redisson</groupId>
	<artifactId>redisson</artifactId>
	<version>3.8.0</version>
</dependency>
속성 설정
application.propertes 자원 파일 에 단기&보초병 관련 설정 추가

server.port=3000

# redisson lock     
redisson.address=redis://127.0.0.1:6379
redisson.password=

#    
#redisson.master-name= master
#redisson.password=
#redisson.sentinel-addresses=10.47.91.83:26379,10.47.91.83:26380,10.47.91.83:26381
주의:
여기 redis:/접 두 사 를 추가 하지 않 으 면 URI 구축 오류 가 발생 합 니 다.

Caused by: java.net.URISyntaxException: Illegal character in scheme name at index 0
더 많은 설정 정 보 는 홈 페이지 에서 볼 수 있 습 니 다.
Lock 의 인터페이스 정의 클래스 정의

package com.tuhu.thirdsample.service;

import org.redisson.api.RLock;
import java.util.concurrent.TimeUnit;
/**
 * @author chendesheng
 * @create 2019/10/12 10:48
 */
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);
}
Lock 인터페이스 구현 클래스

package com.tuhu.thirdsample.service;

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;

import java.util.concurrent.TimeUnit;

/**
 * @author chendesheng
 * @create 2019/10/12 10:49
 */
public class RedissonDistributedLocker implements DistributedLocker{

 private RedissonClient redissonClient;

 @Override
 public RLock lock(String lockKey) {
  RLock lock = redissonClient.getLock(lockKey);
  lock.lock();
  return lock;
 }

 @Override
 public RLock lock(String lockKey, int leaseTime) {
  RLock lock = redissonClient.getLock(lockKey);
  lock.lock(leaseTime, TimeUnit.SECONDS);
  return lock;
 }

 @Override
 public RLock lock(String lockKey, TimeUnit unit ,int timeout) {
  RLock lock = redissonClient.getLock(lockKey);
  lock.lock(timeout, unit);
  return lock;
 }

 @Override
 public 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;
  }
 }

 @Override
 public void unlock(String lockKey) {
  RLock lock = redissonClient.getLock(lockKey);
  lock.unlock();
 }

 @Override
 public void unlock(RLock lock) {
  lock.unlock();
 }

 public void setRedissonClient(RedissonClient redissonClient) {
  this.redissonClient = redissonClient;
 }
}
redisson 속성 조립 클래스

package com.tuhu.thirdsample.common;

import lombok.Data;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

/**
 * @author chendesheng
 * @create 2019/10/11 20:04
 */
@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;

}
SpringBoot 자동 조립 클래스

package com.tuhu.thirdsample.configuration;

import com.tuhu.thirdsample.common.RedissonProperties;
import com.tuhu.thirdsample.service.DistributedLocker;
import com.tuhu.thirdsample.service.RedissonDistributedLocker;

import com.tuhu.thirdsample.util.RedissonLockUtil;
import org.apache.commons.lang3.StringUtils;
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.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


/**
 * @author chendesheng
 * @create 2019/10/12 10:50
 */
@Configuration
@ConditionalOnClass(Config.class)
@EnableConfigurationProperties(RedissonProperties.class)
public class RedissonAutoConfiguration {

 @Autowired
 private 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 ,       RedissLockUtil 
  * @return
  */
 @Bean
 DistributedLocker distributedLocker(RedissonClient redissonClient) {
  DistributedLocker locker = new RedissonDistributedLocker();
  ((RedissonDistributedLocker) locker).setRedissonClient(redissonClient);
  RedissonLockUtil.setLocker(locker);
  return locker;
 }
}
Lock 도움말 클래스

package com.tuhu.thirdsample.util;

import com.tuhu.thirdsample.service.DistributedLocker;
import org.redisson.api.RLock;

import java.util.concurrent.TimeUnit;

/**
 * @author chendesheng
 * @create 2019/10/12 10:54
 */
public class RedissonLockUtil {

 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);
 }
}
제어 층

package com.tuhu.thirdsample.task;

import com.tuhu.thirdsample.common.KeyConst;
import lombok.extern.slf4j.Slf4j;

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;
/**
 * @author chendesheng
 * @create 2019/10/12 11:03
 */
@RestController
@RequestMapping("/lock")
@Slf4j
public class LockController {
 @Autowired
 RedissonClient redissonClient;
 
 @GetMapping("/task")
 public void task(){
  log.info("task start");
  RLock lock = redissonClient.getLock(KeyConst.REDIS_LOCK_KEY);
  boolean getLock = false;

  try {
   if (getLock = lock.tryLock(0,5,TimeUnit.SECONDS)){
    //      
    System.out.println("     ");

   }else {
    log.info("Redisson         :{},ThreadName:{}",KeyConst.REDIS_LOCK_KEY,Thread.currentThread().getName());
   }

  } catch (InterruptedException e) {
   log.error("Redisson         ,    :{}",e);
  }finally {


   if (!getLock){
    return;
   }
   //             ;      
   //lock.unlock();
   //log.info("Redisson       :{},ThreadName :{}", KeyConst.REDIS_LOCK_KEY, Thread.currentThread().getName());
  }
 }

}
RLock 계승 자java.util.concurrent.locks.Lock이 를 재 입 자물쇠 로 이해 할 수 있 습 니 다.수 동 으로 자 물 쇠 를 추가 하고 자 물 쇠 를 풀 어야 합 니 다.
그 중 하 나 를 보 는 방법:try Lock(long wait Time,long lease Time,TimeUnit unit)

getLock = lock.tryLock(0,5,TimeUnit.SECONDS)
try Lock()의 인 자 를 통 해 알 수 있 듯 이 이 자 물 쇠 를 가 져 올 때 다른 스 레 드 에 의 해 먼저 자 물 쇠 를 가 져 오 면 대기 에 들 어가 wait Time 시간 을 기다 리 고 자 물 쇠 를 가 져 올 기회 가 없 으 면 포기 하고 false 로 돌아 갑 니 다.자 물 쇠 를 얻 으 면 unlock 을 호출 하여 풀 지 않 는 한 leaseTime 이 지정 한 시간 을 초과 할 때 까지 자 물 쇠 를 가지 고 있 습 니 다.
이상 은 바로 Redisson 이 분포 식 자 물 쇠 를 실현 하 는 핵심 방법 입 니 다.어떤 사람 이 물 어 볼 수 있 습 니 다.그러면 같은 자 물 쇠 를 가 져 왔 는 지,분포 식 자 물 쇠 는 어디 에 있 는 지 어떻게 확인 합 니까?
이것 이 바로 Redisson 의 강력 한 점 입 니 다.그 밑 에 있 는 Redis 를 사용 하여 분포 식 자 물 쇠 를 만 듭 니 다.우리 의 Redisson Manager 에서 Redis 인 스 턴 스 를 지 정 했 습 니 다.Redisson 은 위탁 관 리 를 할 것 입 니 다.그 원 리 는 우리 가 수 동 으로 Redis 분포 식 자 물 쇠 를 실현 하 는 것 과 유사 합 니 다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기