亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

SpringBoot集成Redisson實(shí)現(xiàn)分布式鎖的方法示例

 更新時(shí)間:2019年10月13日 15:09:46   作者:Joyu_chen  
這篇文章主要介紹了SpringBoot集成Redisson實(shí)現(xiàn)分布式鎖的方法示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

上篇 《SpringBoot 集成 redis 分布式鎖優(yōu)化》對(duì)死鎖的問(wèn)題進(jìn)行了優(yōu)化,今天介紹的是 redis 官方推薦使用的 Redisson ,Redisson 架設(shè)在 redis 基礎(chǔ)上的 Java 駐內(nèi)存數(shù)據(jù)網(wǎng)格(In-Memory Data Grid),基于NIO的 Netty 框架上,利用了 redis 鍵值數(shù)據(jù)庫(kù)。功能非常強(qiáng)大,解決了很多分布式架構(gòu)中的問(wèn)題。

Github的wiki地址: https://github.com/redisson/redisson/wiki

官方文檔: https://github.com/redisson/redisson/wiki/目錄

項(xiàng)目代碼結(jié)構(gòu)圖:

 

導(dǎo)入依賴

<dependency>
	<groupId>org.redisson</groupId>
	<artifactId>redisson</artifactId>
	<version>3.8.0</version>
</dependency>

屬性配置

application.properites 資源文件中添加單機(jī)&哨兵相關(guān)配置

server.port=3000

# redisson lock 單機(jī)模式
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:// 前綴會(huì)報(bào) URI 構(gòu)建錯(cuò)誤

Caused by: java.net.URISyntaxException: Illegal character in scheme name at index 0

更多的配置信息可以去官網(wǎng)查看

定義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接口實(shí)現(xiàn)類

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自動(dòng)裝配類

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;

 /**
  * 哨兵模式自動(dòng)裝配
  * @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);
 }

 /**
  * 單機(jī)模式自動(dòng)裝配
  * @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類,并將實(shí)例注入到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);
 }

 /**
  * 帶超時(shí)的鎖
  * @param lockKey
  * @param timeout 超時(shí)時(shí)間 單位:秒
  */
 public static RLock lock(String lockKey, int timeout) {
  return redissLock.lock(lockKey, timeout);
 }

 /**
  * 帶超時(shí)的鎖
  * @param lockKey
  * @param unit 時(shí)間單位
  * @param timeout 超時(shí)時(shí)間
  */
 public static RLock lock(String lockKey, TimeUnit unit , int timeout) {
  return redissLock.lock(lockKey, unit, timeout);
 }

 /**
  * 嘗試獲取鎖
  * @param lockKey
  * @param waitTime 最多等待時(shí)間
  * @param leaseTime 上鎖后自動(dòng)釋放鎖時(shí)間
  * @return
  */
 public static boolean tryLock(String lockKey, int waitTime, int leaseTime) {
  return redissLock.tryLock(lockKey, TimeUnit.SECONDS, waitTime, leaseTime);
 }

 /**
  * 嘗試獲取鎖
  * @param lockKey
  * @param unit 時(shí)間單位
  * @param waitTime 最多等待時(shí)間
  * @param leaseTime 上鎖后自動(dòng)釋放鎖時(shí)間
  * @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)){
    //執(zhí)行業(yè)務(wù)邏輯
    System.out.println("拿到鎖干活");

   }else {
    log.info("Redisson分布式鎖沒(méi)有獲得鎖:{},ThreadName:{}",KeyConst.REDIS_LOCK_KEY,Thread.currentThread().getName());
   }

  } catch (InterruptedException e) {
   log.error("Redisson 獲取分布式鎖異常,異常信息:{}",e);
  }finally {


   if (!getLock){
    return;
   }
   //如果演示的話需要注釋該代碼;實(shí)際應(yīng)該放開(kāi)
   //lock.unlock();
   //log.info("Redisson分布式鎖釋放鎖:{},ThreadName :{}", KeyConst.REDIS_LOCK_KEY, Thread.currentThread().getName());
  }
 }

}

RLock 繼承自 java.util.concurrent.locks.Lock ,可以將其理解為一個(gè)重入鎖,需要手動(dòng)加鎖和釋放鎖 。

來(lái)看它其中的一個(gè)方法:tryLock(long waitTime, long leaseTime, TimeUnit unit)

getLock = lock.tryLock(0,5,TimeUnit.SECONDS)

通過(guò) tryLock() 的參數(shù)可以看出,在獲取該鎖時(shí)如果被其他線程先拿到鎖就會(huì)進(jìn)入等待,等待 waitTime 時(shí)間,如果還沒(méi)用機(jī)會(huì)獲取到鎖就放棄,返回 false;若獲得了鎖,除非是調(diào)用 unlock 釋放,那么會(huì)一直持有鎖,直到超過(guò) leaseTime 指定的時(shí)間。

以上就是 Redisson 實(shí)現(xiàn)分布式鎖的核心方法,有人可能要問(wèn),那怎么確定拿的是同一把鎖,分布式鎖在哪?

這就是 Redisson 的強(qiáng)大之處,其底層還是使用的 Redis 來(lái)作分布式鎖,在我們的RedissonManager中已經(jīng)指定了 Redis 實(shí)例,Redisson 會(huì)進(jìn)行托管,其原理與我們手動(dòng)實(shí)現(xiàn) Redis 分布式鎖類似。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論