spring boot 实现Redisson分布式锁及其读写锁

分布式锁,就是控制分布式系统中不同进程共同访问同一共享资源的一种锁的实现。
1、引入依赖

<dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.15.5</version></dependency>

2、配置文件

spring:data:redis:database: 1host: localhostport: 6379password: *********

3、配置类

package com.example.springboot3test.config;import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.config.SingleServerConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** @author DeyouKong* @description TODO* @date 2023/3/23 23:34*/@Configuration
public class RedissonConfig {@Value(value = "${spring.data.redis.host}")private String host;@Value(value = "${spring.data.redis.port}")private int port;@Value(value = "${spring.data.redis.database}")private int database;@Value(value = "${spring.data.redis.password}")private String password;/*** 单Redis节点模式配置方法* 其他配置參數,看:* <a href = "https://github.com/redisson/redisson/wiki/2.-%E9%85%8D%E7%BD%AE%E6%96%B9%E6%B3%95#26-%E5%8D%95redis%E8%8A%82%E7%82%B9%E6%A8%A1%E5%BC%8F">* 单Redis节点模式配置方法* </a>** @return {@link RedissonClient}*/@Bean(destroyMethod = "shutdown")RedissonClient redisson() {Config config = new Config();//Redis多节点// config.useClusterServers()//     .addNodeAddress("redis://127.0.0.1:6379", "redis://127.0.0.1:7001");//Redis单节点SingleServerConfig singleServerConfig = config.useSingleServer();//可以用"rediss://"来启用SSL连接String address = "redis://" + host + ":" + port;singleServerConfig.setAddress(address);//设置 数据库编号singleServerConfig.setDatabase(database);singleServerConfig.setPassword(password);//连接池大小:默认值:64// singleServerConfig.setConnectionPoolSize()return Redisson.create(config);}}

4、测试代码

package com.example.springboot3test.controller;import jakarta.annotation.Resource;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
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;@RestController
@RequestMapping("/redission")
public class RedissionController {@Resourceprivate RedissonClient redissonClient;private final static String LOCK="I_AM_LOCK";@GetMapping("/list")public String getString(){// 1、获取一把锁,只要锁的名字一样,既是同一把锁RLock lock = redissonClient.getLock(LOCK);// 2、加锁//lock.lock(5, TimeUnit.SECONDS); // 阻塞式等待if(lock.isLocked()){//如果存在锁,则返回失败return "fail";}lock.lock();try {System.out.println(Thread.currentThread().getName()+":\t 获得锁");Thread.sleep(20000);} catch (Exception e) {e.printStackTrace();return "占用所";}finally {// 3、解锁lock.unlock();System.out.println(Thread.currentThread().getName()+":\t 释放锁锁");}return "OK";}
}

5、理解
一、时间设置
默认 lock() 小结
lock.lock ();
(1)默认指定锁时间为30s(看门狗时间)
(2)锁的自动续期:若是业务超长,运行期间自动给锁上新的 30s,不用担心业务时间过长,锁就自动过期
(3)加锁的业务只要运行完成,就不会给当前锁续期,及时不手动解锁,锁默认在30s 后自动删除。
指定时间 lock() 小结
问题:在锁到期的时候,不会自动续期。
(1)如果我们传递了锁的超时时间,就发送给 redis执行脚本,进行占锁,默认的超时时间既我们指的时间
(2)若是未指定锁的超时时间,就使用 30*1000【LockWatchdogTimeout看门狗的默认时间】
(3)只要占锁成功,就会启动一个定时任务【重新给锁设置过期时间,新的过期时间就是看门狗的默认时间】,每隔 10 s都会自动再次续到30s, internallockLeaseTime【看门狗时间/3s】
二、其他
1、互斥
在分布式高并发的条件下,我们最需要保证,同一时刻只能有一个线程获得锁,这是最基本的一点。

2、防止死锁
在分布式高并发的条件下,比如有个线程获得锁的同时,还没有来得及去释放锁,就因为系统故障或者其它原因使它无法执行释放锁的命令,导致其它线程都无法获得锁,造成死锁。所以分布式非常有必要设置锁的有效时间,确保系统出现故障后,在一定时间内能够主动去释放锁,避免造成死锁的情况。
6、读写锁
读写锁(Readers-Writer Lock)顾名思义是一把锁分为两部分:读锁和写锁,其中读锁允许多个线程同时获得,因为读操作本身是线程安全的,而写锁则是互斥锁,不允许多个线程同时获得写锁,并且写操作和读操作也是互斥的。总结来说,读写锁的特点是:读读不互斥、读写互斥、写写互斥。
实现:首先要配置redis,见前面的博客

spring boot配置redis
读写锁代码

package com.example.springboot3test.controller;import jakarta.annotation.Resource;
import org.redisson.api.RLock;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.UUID;
import java.util.concurrent.TimeUnit;@RestController
@RequestMapping("/redission")
public class RedissionController {@Resourceprivate RedissonClient redissonClient;@Resourceprivate RedisTemplate redisTemplate;private final static String LOCK="I_AM_LOCK";// 并发写锁@GetMapping("/write")public String writeValue(){RReadWriteLock myLock = redissonClient.getReadWriteLock ("my_lock");RLock rLock = myLock.writeLock ( );rLock.lock ();String s = "";try {System.out.println ("写锁加锁成功..."+Thread.currentThread ().getId () );s= UUID.randomUUID ().toString ();Thread.sleep(20000);redisTemplate.opsForValue ().set ("writeValue",s);} catch (Exception e) {e.printStackTrace ();}finally {System.out.println ("写锁解锁成功..."+Thread.currentThread ().getId () );rLock.unlock ();}return s;}// 并发读锁@GetMapping("read")public String readValue(){RReadWriteLock myLock = redissonClient.getReadWriteLock ("my_lock");RLock rLock = myLock.readLock ( );rLock.lock ();String s = "";try {System.out.println ("读锁加锁成功..."+Thread.currentThread ().getId ());Thread.sleep(20000);s = (String) redisTemplate.opsForValue ().get ("writeValue");} catch (Exception e) {e.printStackTrace ( );}finally {System.out.println ("读锁解锁成功..."+Thread.currentThread ().getId () );rLock.unlock ();}return s;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/46563.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

6.Web后端开发【SpringBoot入门】

文章目录 1 SpringBoot快速入门1.1 Web分析 2. HTTP协议2.1 HTTP-概述2.1.1 介绍2.2.2 特点 2.2 HTTP-请求协议2.3 HTTP-响应协议2.3.1 格式介绍2.3.2 响应状态码 常见的相应状态码 3 WEB服务器3.1 服务器概述 1 SpringBoot快速入门 Spring的官网Spring Boot 可以帮助我们非常…

【Git】SSH到底是什么

一、SSH初探 1、SSH是什么&#xff1f; SSH是一个安全协议&#xff0c;类似有SSL、TSL Git有四种协议&#xff1a;本地协议、Git协议、HTTP协议、SSH协议 SSH协议的优缺点&#xff1a; 优点&#xff1a;SSH访问更加安全&#xff0c;有利于公司的开发维护&#xff0c;并且可…

浅拷贝与深拷贝

作者简介&#xff1a; zoro-1&#xff0c;目前大一&#xff0c;正在学习Java&#xff0c;数据结构等 作者主页&#xff1a; zoro-1的主页 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01;&#x1f496;&#x1f496; 浅拷贝与深拷贝 浅拷贝浅拷贝定义浅拷贝代码演示浅…

2023国赛数学建模D题思路模型代码 高教社杯

本次比赛我们将会全程更新思路模型及代码&#xff0c;大家查看文末名片获取 之前国赛相关的资料和助攻可以查看 2022数学建模国赛C题思路分析_2022国赛c题matlab_UST数模社_的博客-CSDN博客 2022国赛数学建模A题B题C题D题资料思路汇总 高教社杯_2022国赛c题matlab_UST数模社…

HCIP-OpenStack组件介绍

openstack把这些组件服务都集成到httpd服务中了&#xff0c;目的是为了提升性能。登入不了openstack在控制节点查下httpd服务&#xff0c;systemctl status httpd Horizon&#xff1a;提供webUI图形化界面的 Keystone&#xff1a;提供身份认证服务、授权、endpoint端点&#xf…

【Mybatis源码分析】解析语句标签_Select|Update|Insert|Delete

解析语句标签 Select|Update|Insert|Delete 一、前言二、语句标签的源码分析三、sql 标签的解析四、总结 一、前言 在阐述解析语句标签之前&#xff0c;得先知道我们的语句标签内容最后被封装到Configuration哪&#xff1f;&#xff08;都应该知道 Mybatis 通过的是 XMLConfig…

排序(七种排序)

1.插入排序 2.希尔排序 3.选择排序 4.堆排序 5.冒泡排序 6.快速排序 7.归并排序 1.插入排序 1.1思路 把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中&#xff0c;直到所有的记录插入完为 止&#xff0c;得到一个新的有序序列 1.2实现 //插入排…

全志orangepi-zero2驱动编写

文章目录 编译内核拓展一下&#xff0c;如果是其他板子内核编译有几种方式&#xff08;可以不用看&#xff09;&#xff1a;以下是树莓派板子的内核编译 驱动编写框架驱动框架 结束 编译内核 编写驱动之前先去官网下载&#xff0c;手册&#xff0c;跳到5.几章先弄好内核编译 照…

openGauss学习笔记-45 openGauss 高级数据管理-物化视图

文章目录 openGauss学习笔记-45 openGauss 高级数据管理-物化视图45.1 全量物化视图45.1.1 全量物化视图语法格式45.1.2 全量物化视图参数说明45.1.3 全量物化视图示例 45.2 增量物化视图45.2.1 增量物化视图语法格式45.2.2 增量物化视图参数说明45.2.3 增量物化视图示例 openG…

工厂模式并不难理解

文章目录 工厂模式简单工厂模式简单工厂模式使用的场景 工厂方法模式工厂方法模式使用场景 抽象工厂模式抽象工厂模式使用场景 工厂模式 功能&#xff1a;将对象的创建交给工厂&#xff0c;我们只需要告诉工厂我们要什么对象就可以得到该对象。 目的&#xff1a;实现创建对象…

【算法刷题之链表篇(1)】

目录 1.leetcode-82. 删除排序链表中的重复元素 II&#xff08;1&#xff09;题目描述&#xff08;2&#xff09;方法及思路&#xff08;一次遍历&#xff09;&#xff08;3&#xff09;代码实现 2.leetcode-19. 删除链表的倒数第 N 个结点&#xff08;1&#xff09;题目描述&a…

【问题】java序列化,什么时候使用

文章目录 是什么为什么如何做流操作 注事事项 是什么 把对象转换为字节序列的过程称为对象的序列化。 把字节序列恢复为对象的过程称为对象的反序列化。 对象的序列化主要有两种用途&#xff1a;   1&#xff09;把对象的字节序列永久地保存到硬盘上&#xff0c;通常存放在一…

二刷LeetCode--46. 全排列(C++版本),回溯

思路&#xff1a;本题是典型的回溯问题&#xff0c;需要列举出每个排列&#xff0c;因此使用回溯法&#xff0c;对每个使用过的元素进行标记&#xff0c;因此需要一个和Nums同样大的标记数组&#xff0c;每个元素被使用之后在递归之前将其标记为已使用&#xff0c;在递归的时候…

JavaScript面试题(四)

87、事件代理 事件代理 也就是 事件委托不是直接给标签添加事件 是给标签的父级添加事件 通过 事件对象 判断触发事件的标签对象是谁 执行不同的函数程序的语法形式委托的优点减少内存消耗 试想一下&#xff0c;若果我们有一个列表&#xff0c;列表之中有大量的列表项&#xf…

无需公网IP——搭建web站点

文章目录 概述使用 Raspberry Pi Imager 安装 Raspberry Pi OS设置 Apache Web 服务器测试 web 站点安装静态样例站点将web站点发布到公网安装 Cpolar内网穿透cpolar进行token认证生成cpolar随机域名网址生成cpolar二级子域名将参数保存到cpolar配置文件中测试修改后配置文件配…

认识容器,走进Docker

文章目录 容器技术简介容器的核心技术容器平台技术容器的支持技术 Docker理念Docker安装配置阿里云镜像加速器 容器技术简介 一切在云端&#xff0c;万物皆容器&#xff0c;说到容器&#xff0c;大家都会想到Docker,Docker现在几乎是容器的代名词&#xff0c;什么是Docker&…

网络通信原理TCP的四次断开连接(第四十九课)

FIN:发端完成发送任务标识。用来释放一个连接。FIN=1表明此报文段的发送端的数据已经发送完毕,并要求释放连接。 SEQ:序号字段。 TCP链接中传输的数据流中每个字节都编上一个序号。序号字段的值指的是本报文段所发送的数据的第一个字节的序号。 序列号为X ACK :确认号 。 …

ViT模型架构和CNN区别

目录 Vision Transformer如何工作 ViT模型架构 ViT工作原理解析 步骤1&#xff1a;将图片转换成patches序列 步骤2&#xff1a;将patches铺平 步骤3&#xff1a;添加Position embedding 步骤4&#xff1a;添加class token 步骤5&#xff1a;输入Transformer Encoder 步…

【Rust】Rust学习 第十五章智能指针

指针 &#xff08;pointer&#xff09;是一个包含内存地址的变量的通用概念。这个地址引用&#xff0c;或 “指向”&#xff08;points at&#xff09;一些其他数据。Rust 中最常见的指针是第四章介绍的 引用&#xff08;reference&#xff09;。引用以 & 符号为标志并借用…

C# Linq源码分析之Take (三)

概要 本文在前两篇Take源码分析的基础上&#xff0c;着重分析Range参数中有倒数的情况&#xff0c;即分析TakeRangeFromEndIterator的源码实现。 源码及分析 TakeRangeFromEndIterator方法用于处理Range中的开始和结束索引存在倒数的情况。该方法位于Take.cs文件中。通过yie…