Redisson-分布式锁单Redis节点模式

Redisson-分布式锁单Redis节点模式

为什么要用分布式锁?

使用分布式锁的主要目的是为了解决多线程或多进程并发访问共享资源时可能出现的竞争条件和数据一致性问题。举一些实际场㬌:

  1. 数据库并发控制:在分布式系统中,多个节点同时操作数据库时,可能会导致数据不一致或冲突。通过使用分布式锁,可以确保同一时间只有一个节点能够对特定数据进行修改,从而避免出现脏读、幻读等问题。
  2. 资源限制和瓶颈控制:某些资源(如文件、接口调用次数等)需要限制同时访问的数量,在高并发环境下通过使用分布式锁可以有效地控制资源的访问数量。
  3. 防止死锁:在复杂系统中,由于各种原因(如网络故障、程序错误等),可能导致死锁情况。通过使用带有超时机制的分布式锁,可以防止因为单个节点故障而导致整个系统陷入死锁状态。

使用分布式锁能够保证共享资源被安全地访问和修改,并且能够提供良好的并发性能和可靠性。

目前的市场使用的分布式锁有哪些?(个人了解不代表所有)

  1. 基于数据库的分布式锁
    优点:简单易实现,使用现有的数据库即可,不需要额外的基础设施。
    缺点:性能相对较低,数据库的I/O操作开销大,还需要处理数据库的死锁问题。

  2. 基于Redis的分布式锁
    优点:高性能,Redis是内存数据库,读写速度快,Redis支持多种数据结构,灵活性高。
    缺点:需要确保Redis集群的高可用性和一致性,否则可能导致锁的失效。

  3. 基于Redisson的分布式锁
    优点: 内置多种锁的实现,适用于不同场景,提高了锁的可靠性。
    缺点:封装了很多功能,引入了一些额外的开销,相对直接使用Redis的命令,增加了项目依赖。

  4. 基于Zookeeper的分布式锁
    优点:实现分布式锁的过程中能够自动处理网络分区和节点故障,支持临时节点,可以自动释放锁。
    缺点:实现较为复杂!!!性能相对Redis较低,因为Zookeeper需要维护强一致性。

使用Redisson实现分布式锁

我用的是Spring Boot 的框架,没有什么心思写文章就直接写代码吧~

demo包类结构
在这里插入图片描述
pom.xml

<dependencies><!--  redis缓存  --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- Redisson分布式锁   --><dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.12.0</version></dependency></dependencies>

yml配置

server:port: 8081servlet:context-path: /api
spring:redis:host: 服务器ipport: 6379
#    password: 123456timeout: 60000database: 5

配置类

package com.springboot.redisson.config;import lombok.Data;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.config.SingleServerConfig;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;@Data
@Configuration
@ConfigurationProperties("spring.redis")
public class RedissonConfig {private String host;private String password;private String port;private int timeout = 3000;private int connectionPoolSize = 64;private int connectionMinimumIdleSize=10;private int pingConnectionInterval = 60000;private static String ADDRESS_PREFIX = "redis://";/*** 自动装配**/@BeanRedissonClient redissonSingle() {Config config = new Config();//  判断redis 的host是否为空if(StringUtils.isEmpty(host)){throw new RuntimeException("host is  empty");}//  配置host,port等参数SingleServerConfig serverConfig = config.useSingleServer()// 节点地址.setAddress(ADDRESS_PREFIX + this.host + ":" + port)// 命令等待超时,单位:毫秒.setTimeout(this.timeout).setPingConnectionInterval(pingConnectionInterval)// 连接池大小.setConnectionPoolSize(this.connectionPoolSize)// 最小空闲连接数.setConnectionMinimumIdleSize(this.connectionMinimumIdleSize);//  判断进入redis 是否密码if(!StringUtils.isEmpty(this.password)) {serverConfig.setPassword(this.password);}return Redisson.create(config);}
}

controller

package com.springboot.redisson.controller;import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RCountDownLatch;
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.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import java.util.UUID;
import java.util.concurrent.TimeUnit;@Slf4j
@RestController
@RequestMapping("redisson")
public class RedissonController {@ResourceRedissonClient redissonSingle;@ResourceRedisTemplate<String,Object> redisTemplate;@GetMapping("/")private String TestString(){return "Hello redisson!";}/*** RLock lock = redissonSingle.getLock("my-redisson-lock");* lock.lock();* 使用的是可重入锁*  可重入锁: 可重入锁是一个分布式锁,它可以用于多个线程访问同一把锁的等待保证数据的唯一性*      例如: 当有一个线程在访问一个可重入锁的时候,就会自动加锁,其它线程再次访问同一把锁有时候只能等待,*              当线程释放锁的时候,其它线程才可以访问,每次只能有一个线程进行访问,* @return*/@GetMapping("no1")public String TestRedisson01(){RLock lock = redissonSingle.getLock("my-redisson-lock");lock.lock();try {log.info("NO1加锁成功,正在处理业务逻辑》》》》》");System.out.println("好长的业务");Thread.sleep(50000);} catch (InterruptedException e) {throw new RuntimeException(e);}finally {lock.unlock();log.info("NO1解锁成功");}return "NO1线程已经走完成!";}@GetMapping("no2")public String TestRedisson02(){RLock lock = redissonSingle.getLock("my-redisson-lock");lock.lock();try {log.info("NO2加锁成功,正在处理业务逻辑》》》》》");System.out.println("好长的业务");Thread.sleep(50000);} catch (InterruptedException e) {throw new RuntimeException(e);}finally {lock.unlock();log.info("NO2解锁成功");}return "NO2线程已经走完成!";}/*** 读写锁*   RReadWriteLock readWriteLock = redissonSingle.getReadWriteLock("my-lock");*         RLock rLock = readWriteLock.readLock();*         rLock.lock();*         rLock.unlock();*   读写锁: 读写锁是一个分布式锁,它允许多个线程同时读,但是只允许一个线程写,写操作的时候,读操作会被阻塞,*/@GetMapping("read")public String TestReadLock(){RReadWriteLock readWriteLock = redissonSingle.getReadWriteLock("my-lock");RLock rLock = readWriteLock.readLock();rLock.lock();String s = "";try {log.info("读写锁操作中,正在处理业务逻辑》》》》》");s = UUID.randomUUID().toString();redisTemplate.opsForValue().set("redisson:readWriteLock",s,200, TimeUnit.SECONDS);Thread.sleep(5000);}catch (Exception e){e.printStackTrace();}finally {rLock.unlock();}return s;}@GetMapping("writel")public String TestWriteLock(){RReadWriteLock readWriteLock = redissonSingle.getReadWriteLock("my-lock");RLock rLock = readWriteLock.writeLock();rLock.lock();String s = "";try {log.info("读锁操作中,正在处理业务逻辑》》》》》");String key = (String) redisTemplate.opsForValue().get("redisson:readWriteLock");if (!StringUtils.isEmpty(key)){s = key;}}catch (Exception e){e.printStackTrace();}finally {rLock.unlock();}return s;}/*** 闭锁*  RCountDownLatch door = redissonSingle.getCountDownLatch("door");*             door.trySetCount(5);*             door.await();**             door.countDown();*  闭锁: 闭锁是一个分布式闭锁,它允许一个或多个线程等待,直到其他线程完成一系列操作,然后才继续执行。*/@GetMapping("/lockDoor")public String lockDoor(){try {RCountDownLatch door = redissonSingle.getCountDownLatch("door");door.trySetCount(5);door.await();} catch (InterruptedException e) {throw new RuntimeException(e);}return "放假了。。。。。";}@GetMapping("/gogo/{id}")public String gogo(@PathVariable("id")String id){RCountDownLatch door = redissonSingle.getCountDownLatch("door");door.countDown();return id+"班的人都走了。。。。。";}@GetMapping("/modify")public String modifyData(){RLock lock = redissonSingle.getLock("my_modify_locl");if (!lock.tryLock()){return "修改失败,当前信息正在被人修改";}try {System.out.println("运行一个超长代码中");Thread.sleep(50000);return "修改成功";}catch (Exception e){e.printStackTrace();}finally {lock.unlock();}return "最后的代码";}
}

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

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

相关文章

从0开始实现一个博客系统 (SSM 实现)

相关技术 Spring Spring Boot Spring MVC MyBatis Html Css JS 实现功能 用户注册 - 密码加盐加密 (md5 加密)前后端用户信息存储 - 令牌技术用户登录 - (使用 拦截器 做登录校验)博客的增删改查后端数据返回前端, 采用 SpringBoot 做统一功能处理和统一异常处理 数据…

软考-程序员 知识点与部分真题梳理

软考-程序员 知识点与部分真题梳理 参照《程序员教程》第五版划分类别&#xff1b; 持续更新中… 计算机系统基础知识 如何理解和处理浮点数的加减法运算 在计算机科学中&#xff0c;处理浮点数的表示和运算是基础且关键的&#xff0c;尤其是在进行科学计算、图形处理和数据分…

【网络】为什么udp协议报头有长度字段,而tcp没有

引言&#xff1a; 在网络通信中&#xff0c;UDP&#xff08;用户数据报协议&#xff09;和TCP&#xff08;传输控制协议&#xff09;是两种常用的传输层协议。它们在设计和功能上有一些不同之处&#xff0c;其中之一就是报头中的长度字段。本文将深入探讨UDP和TCP协议中长度字…

SpringCloud Alibaba详解:打造高可用的分布式系统

SpringCloud Alibaba是一个基于Spring Cloud的微服务开发框架&#xff0c;它集成了阿里巴巴的一系列中间件和工具&#xff0c;能够快速构建高可用的分布式系统。在本文中&#xff0c;将详细介绍如何使用SpringCloud Alibaba来打造高可用的分布式系统&#xff0c;并通过代码案例…

第十一课,end关键字、简单while循环嵌套、初识for循环

一&#xff0c;end关键字 end关键字用于在print输出的内容后面声明结束的字符&#xff0c;我们之前学过并且十分了解print是默认输出内容之后跟着换行的&#xff0c;如果我们不希望换行而希望使用其它字符来代替换行&#xff0c;就可以用end关键字来实现 特殊的&#xff0c;en…

Redis机制-Redis缓存穿透,击穿,雪崩理解等问题的理解和学习

目录 一 缓存穿透问题 二 缓存击穿问题 三 缓存雪崩问题&#xff1a; 图1 正常的Redis缓存流程 一 缓存穿透问题 我们都知道Redis是一个存储键值对的非关系型数据库&#xff0c;那么当用户进行查询的时候&#xff0c;势必会从前端发起请求&#xff0c;从而数据从Redis缓存…

内网穿透--Frp-简易型(速成)-上线

免责声明:本文仅做技术交流与学习... 目录 frp项目介绍: 一图通解: ​编辑 1-下载frp 2-服务端(server)开启frp口 3-kali客户端(client)连接frp服务器 4-kali生成马子 5-kali监听 6-马子执行-->成功上线 frp项目介绍: GitHub - fatedier/frp: A fast reverse proxy…

论文精读-SwinIR Image Restoration Using Swin Transformer

论文精读-SwinIR: Image Restoration Using Swin Transformer SwinIR:使用 Swin Transformer进行图像恢复 参数量&#xff1a;SR 11.8M、JPEG压缩伪影 11.5M、去噪 12.0M 优点&#xff1a;1、提出了新的网络结构。它采用分块设计。包括浅层特征提取&#xff1a;cnn提取&#…

Verilog实战学习到RiscV - 1 : Yosys 综合

Yosys 综合 实例 一般 FPGA IDE 的第一步都是RTL 综合&#xff08;Synthesis&#xff09;。之后就能看到数字电路图了。然后可以做RTL 级的仿真模拟。 直接上代码&#xff0c;这里我们看一个简单的加法器来学习。 module adder(input [7:0] a,input [7:0] b, input …

Java延时队列取消未支付的订单 之 重启服务任务丢失

一、定义延迟任务类 package com.activity.domain;import java.util.concurrent.Delayed; import java.util.concurrent.TimeUnit;/*** 延迟任务类*/ public class DelayedCancellation implements Delayed {private String order;private final long delayTime; // 延迟时间p…

智能体之斯坦福AI小镇(Generative Agents: Interactive Simulacra of Human Behavior)

相关代码地址见文末 论文地址&#xff1a;Generative Agents: Interactive Simulacra of Human Behavior | Proceedings of the 36th Annual ACM Symposium on User Interface Software and Technology 1.概述 论文提出了一种多个智能体进行协同&#xff0c;进而模拟可信的人…

Linux系统下Mysql忘记密码怎么解决

一、对Mysql配置文件进行设置 1、找到/etc/mysql/my.cnf路径下&#xff0c;用Vi命令编辑my.cnf配置文件&#xff0c;命令如下&#xff1a; # 以管理员身份登录 sudo su # 输入管理员密码 # 登录成功后&#xff0c;找到Mysql的配置文件-->Mysql配置文件默认在此 cd /etc/my…

善用KEGG数据库挖掘目的基因

有关KEGG的分析在很多已发表的论文中都十分常见&#xff0c;涉及到的方向也很广泛&#xff0c;比如&#xff1a;代谢组、表观组、转录组等等。通常得到相关的基因集或者代谢物后&#xff0c;我们都希望能够快速了解它们的蛋白功能和涉及的调控机制&#xff0c;从而进一步锁定接…

NetSuite Intercompany COGS科目设置问题

在22年底的NetSuite多公司功能串讲中&#xff0c;有一个题目是Intercompany COGS科目的设置问题。近期在项目上这个问题被密集讨论。为了方便分享&#xff0c;所以在此摘出来独立成文。有兴趣的同学也可以翻看之前的视频。 NetSuite知识会 第8谈 多公司功能串讲 NetSuite Inter…

图论(从数据结构的三要素出发)

文章目录 逻辑结构物理结构邻接矩阵定义性能分析性质存在的问题 邻接表定义性能分析存在的问题 十字链表(有向图)定义性能分析 邻接多重表(无向图)定义性能分析 数据的操作图的基本操作图的遍历广度优先遍历&#xff08;BFS&#xff09;算法思想和实现性能分析深度优先最小生成…

WORD、PPT技巧

WORD技巧 编辑设置 word标题导航窗口怎么调出word2016&#xff0c;缩小了页面&#xff0c;可是怎么是竖着的一页一页排列啊&#xff1f;以前不是好几页横排着的么&#xff1f;怎么设置&#xff0c;求救&#xff1a;在Word标题栏那一行找到“视图”&#xff0c;点击“显示比例…

20212416 2023-2024-2 《移动平台开发与实践》第5次作业

百度地图应用 1.实验内容2.实验过程2.1 Android Studio配置2.1. 创建一个Android项目2.2 在项目中本地集成BaiduMap SDK 2.2 编写代码2.2.1 配置AndroidManifest.xml文件2.2.2 编写UI界面布局文件2.2.3 编写主函数代码2.2.4 运行结果 3.学习中遇到的问题及解决4.学习感悟与思考…

数据结构篇其三---链表分类和双向链表

​ 前言 数据结构篇其二实现了一个简单的单链表&#xff0c;链表的概念&#xff0c;单链表具体实现已经说明&#xff0c;如下&#xff1a; 单链表 事实上&#xff0c;前面的单链表本质上是无头单向不循环链表。此篇说明的双向链表可以说完全反过来了了。无论是之前的单链表还…

Java进阶学习笔记12——final、常量

final关键字&#xff1a; final是最终的意思。可以修饰类、方法、变量。 修饰类&#xff1a;该类就被称为最终类&#xff0c;特点是不能被继承了。 修饰方法&#xff1a;该方法是最终方法&#xff0c;特点是不能被重写了。 修饰变量&#xff1a;该变量只能被赋值一次。 有些…

智慧校园的建设思路

智慧校园建设的一个主要目的就是要打破学校内的信息孤岛&#xff0c;其核心是在人、流程和信息三个层面的全面整合。智慧校园应该能够为全校师生员工及校外用户提供统一的、一站式的服务渠道&#xff1b;能够将学校各种业务流程连接起来&#xff0c;实现各种应用系统的互联互通…