redisson的锁的类型_SpringBoot集成Redisson实现分布式锁的方法示例_weixin_39816062的博客-程序员宅基地

技术标签: redisson的锁的类型  

上篇 《SpringBoot 集成 redis 分布式锁优化》对死锁的问题进行了优化,今天介绍的是 redis 官方推荐使用的 Redisson ,Redisson 架设在 redis 基础上的 Java 驻内存数据网格(In-Memory Data Grid),基于NIO的 Netty 框架上,利用了 redis 键值数据库。功能非常强大,解决了很多分布式架构中的问题。

项目代码结构图:

导入依赖

org.redisson

redisson

3.8.0

属性配置

在 application.properites 资源文件中添加单机&哨兵相关配置

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 ,可以将其理解为一个重入锁,需要手动加锁和释放锁 。

来看它其中的一个方法:tryLock(long waitTime, long leaseTime, TimeUnit unit)

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

通过 tryLock() 的参数可以看出,在获取该锁时如果被其他线程先拿到锁就会进入等待,等待 waitTime 时间,如果还没用机会获取到锁就放弃,返回 false;若获得了锁,除非是调用 unlock 释放,那么会一直持有锁,直到超过 leaseTime 指定的时间。

以上就是 Redisson 实现分布式锁的核心方法,有人可能要问,那怎么确定拿的是同一把锁,分布式锁在哪?

这就是 Redisson 的强大之处,其底层还是使用的 Redis 来作分布式锁,在我们的RedissonManager中已经指定了 Redis 实例,Redisson 会进行托管,其原理与我们手动实现 Redis 分布式锁类似。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_39816062/article/details/111540287

智能推荐

tcpdump抓包ftp协议_tcpdump抓包分析详解_weixin_39617318的博客-程序员宅基地

tcpdump抓包分析详解[[email protected]~]#tcpdump[-nn][-i接口][-w储存档名][-c次数][-Ae][-qX][-r档案][所欲撷取的数据内容]参数:-nn:直接以IP及portnumber显示,而非主机名与服务名称-i:后面接要『监听』的网络接口,例如eth0,lo,ppp0等等的界面;-w:如果你要将监听所得的封包数据储存下来,用这个参数就对了!后面接档名-...

树莓派python3.7_树莓派4B每次刷装完系统要做的事情,收藏一劳永逸,换源+python3.7+配置中文+开启VNC(避坑)+固定树莓派IP..._weixin_39986543的博客-程序员宅基地

树莓派4B每次刷装完系统要做的配置前言无键盘启动(主要实现自动连接wifi和开启ssh远程访问)第一次启动树莓派换源开启VNC(记得更改原来的分辨率)删除Python2.7(太旧了,和python3.7语法略有出入,可能会导致bug),让系统默认使用Python3.7切换中文和安装中文输入法((自己选择,也可以用英文))固定树莓派IP前言本贴是个人总结,都是经过实践,也是我自己每次重刷系统做的事情...

linux 终端 编辑文件,Linux基础学习系列——Linux文本文件编辑命令_weixin_39848097的博客-程序员宅基地

Linux文本文件编辑命令cat命令more命令head命令tail命令tr命令wc命令stat命令cut命令diff命令cat命令cat命令用于查看内容较少的纯文本文件。格式:cat [选项] 文件说明:Linux系统中有多个用于查看文本内容的命令,每个命令都有自己的特点,比如这个cat命令就是用于查看内容较少的纯文本文件的。如果想要显示行号的话,可以在cat命令后面追加一个-n参数。示例,使用...

百兆以太网接口高速PCB布局布线指南_陈小勇-TT的博客-程序员宅基地

百兆以太网接口高速PCB布局布线指南以太网(Ethernet)执行的是IEEE 802.3 标准,传输数据的模式为CDMA/CD,可使用光纤、双绞线、细缆、粗缆作为传输介质。这里所说的以太网是传统的以太网,10Mbps以太网,一共有四种标准 (1)10Base-5:粗缆网络,区段最大长度为500m。 (2)...

您的计算机运行的可能是盗版,为何我的电脑总跳出来:"您的电脑可能是WINDOW盗版的受害者"..._苏小铁的博客-程序员宅基地

电脑启动后每次都出现“您可能是软件盗版的受害者,此Windows副本未通过正版Windows验证”解决方法微软3月28日发布了更新KB905474,这是微软的最新验证正版还是盗版的补丁,如果您实用的不是正版Windows ,系统启动就会提示你的操作系统是盗版。XP的一个新补丁Windows Genuine Advantage 通知(KB905474),如果您使用的是盗版的Windows XP,安装...

pyqt5必须和python对应_Python PyQt5安装和使用_weixin_39876145的博客-程序员宅基地

QT 是 Linux 桌面 KDE 的开发包,目前支持 Windows、macOS 和 Linux 等操作系统。QT 的历史相当悠久,早在 1991 年,QT 就进入了开发阶段,不过那时的目标操作系统仅是安装有 X11 的 Linux 系统和 Windows。目前 QT 的大版本是 5,所以也被称作 QT5。QT 是一个 C++ 语言的开发包,本节介绍的是该开发包的 Python 版本,由于最新的...

随便推点

c 连接mysql时不能解析引用_c,c++_c++引用c函数时,报错误 error LNK2001: 无法解析的外部符号,c,c++ - phpStudy..._小明斗的博客-程序员宅基地

c++引用c函数时,报错误 error LNK2001: 无法解析的外部符号我的c头文件是这么写的#ifdef __cplusplusextern "C" {#endifextern int shmdb_initParent(STHashShareHandle *handle,unsigned int size);#ifdef __cplusplus}#endif我的c++代码是这么写的//引用头...

微型计算机责任,微机室安全责任书_小星星灯的博客-程序员宅基地

尤镇中心小学2012年1月1为进一步落实我校教育教学安全稳定责任制,创建"平安校园",落实“谁主管、谁负责”的原则,切实保障学校的教育教学工作的健康有序的开展,强化安全防范意识,严格上机操作程序,确保微机室设备和师生人身安全,从源头上杜绝学校安全事故的发生,现根据微机室管-理-员的岗位职责,特签订本责任书:一、微机室管-理-员为微机室安全第一责任人。二、必须加强师生的安全教育,严格遵守微机室的各项...

java+tag的用法_J2EE中自定义标签以及TagSupport和BodyTagSupport的用法_weixin_40009026的博客-程序员宅基地

StringAppendTagspackage cn.xy.myTag;import javax.servlet.jsp.JspException;import javax.servlet.jsp.tagext.TagSupport;public class StringAppendTags extends TagSupport{private static final long serialVe...

黑色星期五--蓝桥杯_weixin_30849403的博客-程序员宅基地

问题描述  有些西方人比较迷信,如果某个月的13号正好是星期五,他们就会觉得不太吉利,用古人的说法,就是“诸事不宜”。请你编写一个程序,统计出在在这一年中,既是13号又是星期五的日期。说明:(1)一年有365天,闰年有366天,所谓闰年,即能被4整除且不能被100整除的年份,或是既能被100整除也能被400整除的年份;(2)已知1998年1月1日是星期四,用户输入的年份肯定大于或等于199...

java list转json报错_List转换成JSON对象报错(一)_合才童子的博客-程序员宅基地

List转换成JSON对象1、具体报错如下Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/lang/exception/NestableRuntimeExceptionat java.lang.ClassLoader.defineClass1(Native Method)at java.la...

微信小游戏利用nginx实现wss转ws的配置文件_weixin_30493401的博客-程序员宅基地

upstream gateway21000 { server 127.0.0.1:21000;}server { listen 443; ssl on; ssl_certificate cert/leshu.com_bundle.crt; ssl_certificate_key cert/server.key; ...

推荐文章

热门文章

相关标签