商城项目【尚品汇】07分布式锁-2 Redisson篇

文章目录

  • 1 Redisson功能介绍
  • 2 Redisson在Springboot中快速入门(代码)
    • 2.1 导入依赖
    • 2.2 Redisson配置
    • 2.3 将自定义锁setnx换成Redisson实现(可重入锁)
  • 3 可重入锁原理
    • 3.1 自定义分布式锁setnx为什么不可以重入
    • 3.2 redisson为什么可以实现可重入
      • 3.2.1 获取锁的lua脚本
      • 3.2.2 释放锁的lua脚本

1 Redisson功能介绍

基于自定义setnx实现的分布式锁存在下面的问题:

重入问题:重入问题是指 获得锁的线程可以再次进入到相同的锁的代码块中,可重入锁的意义在于防止死锁,比如HashTable这样的代码中,他的方法都是使用synchronized修饰的,假如他在一个方法内,调用另一个方法,那么此时如果是不可重入的,不就死锁了吗?所以可重入锁他的主要意义是防止死锁,我们的synchronized和Lock锁都是可重入的。

不可重试:是指目前的分布式只能尝试一次,我们认为合理的情况是:当线程在获得锁失败后,他应该能再次尝试获得锁。

**超时释放:**我们在加锁时增加了过期时间,这样的我们可以防止死锁,但是如果卡顿的时间超长,虽然我们采用了lua表达式防止删锁的时候,误删别人的锁,但是毕竟没有锁住,有安全隐患

主从一致性: 如果Redis提供了主从集群,当我们向集群写数据时,主机需要异步的将数据同步给从机,而万一在同步过去之前,主机宕机了,就会出现死锁问题。
在这里插入图片描述
那么什么是Redisson呢

Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式服务,其中就包含了各种分布式锁的实现。

Redission提供了分布式锁的多种多样的功能
在这里插入图片描述

2 Redisson在Springboot中快速入门(代码)

2.1 导入依赖

<!-- redisson -->
<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.15.3</version>
</dependency>

2.2 Redisson配置

package com.atguigu.gmall.common.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;/*** redisson配置信息*/
@Data
@Configuration
@ConfigurationProperties("spring.redis")
public class RedissonConfig {private String host;private String addresses;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();if(StringUtils.isEmpty(host)){throw new RuntimeException("host is  empty");}SingleServerConfig serverConfig = config.useSingleServer()//redis://127.0.0.1:7181.setAddress(ADDRESS_PREFIX + this.host + ":" + port).setTimeout(this.timeout).setPingConnectionInterval(pingConnectionInterval).setConnectionPoolSize(this.connectionPoolSize).setConnectionMinimumIdleSize(this.connectionMinimumIdleSize);if(!StringUtils.isEmpty(this.password)) {serverConfig.setPassword(this.password);}// RedissonClient redisson = Redisson.create(config);return Redisson.create(config);}
}

2.3 将自定义锁setnx换成Redisson实现(可重入锁)

实现类详细看这个章节:https://blog.csdn.net/yu_fu_a_bu/article/details/139408497

    @GetMapping("testRedisLock")public Result testRedisLock(){testLockService.testRedisLock();return Result.ok();}
    @Autowiredprivate RedissonClient redissonClient;@Overridepublic void testRedisson() {//创建可重入锁对象,并指定锁的名称RLock lock = redissonClient.getLock("redisson:1");//获取锁,循环重试的时间,逻辑过期时间,时间单位boolean isLock = false;try {isLock = lock.tryLock(1, 10, TimeUnit.SECONDS);} catch (InterruptedException e) {e.printStackTrace();System.out.println("获取锁出现异常");}//获取锁成功,执行业务逻辑if (isLock){try{//从缓存中获取值String num = stringRedisTemplate.opsForValue().get("redissonLock");//加1操作int i = Integer.parseInt(num)+1;String s = StringUtil.toString(i);//存储到redis中stringRedisTemplate.opsForValue().set("redissonLock",s);}finally {//只有获取到锁的线程,才去释放锁,lock.unlock();}}}

测试
在这里插入图片描述

ab -n 5000 -c 100 http://192.168.142.1:81/admin/product/testLock/testRedisson

在这里插入图片描述
在这里插入图片描述

3 可重入锁原理

3.1 自定义分布式锁setnx为什么不可以重入

数据结构:key-value的形式。String类型
在这里插入图片描述

public class DistributedLockExample {private static Jedis jedis = new Jedis("127.0.0.1", 6379);public void acquireLock(String lockKey) {Boolean locked = jedis.setnx(lockKey, "true");if (locked) {System.out.println("Lock acquired successfully.");} else {System.out.println("Lock already acquired by another process.");}}public static void main(String[] args) {DistributedLockExample example = new DistributedLockExample();example.acquireLock("myLock");example.acquireLock("myLock"); // 尝试重入}
}

在上面的示例中,acquireLock方法通过setnx尝试获取锁。第一次调用acquireLock时成功获取锁,因为myLock这个key在Redis中不存在。第二次调用acquireLock尝试重入时,会返回锁已被占用的提示,因为Redis的setnx指令无法识别重入情况,每次获取锁都需要先检查是否已被占用。

3.2 redisson为什么可以实现可重入

数据类型:key-value(field-value) Hash类型在这里插入图片描述

不仅存入线程标识(保证不删除别人的锁),而且存入可重入的次数(保证可重入)。

在这里插入图片描述

3.2.1 获取锁的lua脚本

lua脚本可以保证原子性

local key = KEYS[1];--锁的key
local threadId = ARGV[1]; --线程的唯一标识
local releaseTime = ARGV[2];--锁的自动释放时间
--判断锁是否存在
if(redis.call('exists',key) == 0) then --不存在,获取锁redis.call('hset', key,threadId,'1');--设置有效期redis.call('expire',key,releaseTime);return 1;--返回结果
end;
--如果锁已经存在,判断threadId是否是自己的
if(redis.call('hexists',key,threadId) == 1) then--存在,获取锁,重入次数加一redis.call('hincrby',key,threadId,'1');-- 设置有效期redis.call('expire',key,releaseTime);return 1;--返回结果
end;
return 0;--获取锁失败

3.2.2 释放锁的lua脚本

local key = KEYS[1];--锁的key
local threadId = ARGV[1]; --锁的唯一标识
local releaseTime = ARGV[2];--锁的自动释放时间
-- 判断锁是还是被自己持有
if(redis.call('HEXISTS',key,threadId) == 0) then return nil;--如果已经不是自己,则直接返回
end;
-- 是自己的锁,则可重入的次数进行-1
local count = redis.call('HINCRVY',key,threadId,-1);
-- 判断可重入的次数是否为0
if(count > 0){-- 大于0说明不能释放锁,重置过期时间然后返回redis.call('EXPIRE',key,releaseTime);return nil;
else --等于0说明可以释放锁,直接删除redis.call('DEL',key);return nil;
end;

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

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

相关文章

华为面经整理

文章目录 实习第一面准备提问相关算法相关 第一面结果提问环节 总结 实习 第一面准备 提问相关 操作系统有哪些功能 进程管理&#xff1a; 进程调度、进程同步和通信、多任务处理 内存管理&#xff1a; 内存分配、虚拟内存技术、内存保护 文件系统管理&#xff1a; 文件存储…

数据中心网络架构设计与优化

数据中心是现代企业和组织的核心基础设施&#xff0c;它们用于存储、处理和传输大量的数据和信息。为了满足不断增长的数据需求和提供可靠的服务&#xff0c;设计和优化数据中心网络架构至关重要。 首先&#xff0c;数据中心网络架构设计需要考虑可扩展性。随着业务的增长&…

【Pycharm】功能介绍

1.Code Reformat Code 格式化代码&#xff0c;可以帮助我们去自动调整空格等&#xff0c;根据python语法规范自动调整 2.Settings 1.创建py文件默认填充模版 3.读写py文件编码格式一致性 顶部代码指定的编码方式作用&#xff1a; 可以保证python2/3解释器在读取文件的时候按…

【SpringBoot + Vue 尚庭公寓实战】租期管理接口实现(四)

【SpringBoot Vue 尚庭公寓实战】租期管理接口实现&#xff08;四&#xff09; 文章目录 【SpringBoot Vue 尚庭公寓实战】租期管理接口实现&#xff08;四&#xff09;1、查询全部租期列表2、保存或更新租期信息3、根据ID删除租期 租期管理共有三个接口&#xff0c;分别是 保…

MySQL中获取时间的方法

大家好&#xff0c;在MySQL数据库开发中&#xff0c;获取时间是一个常见的需求。MySQL提供了多种方法来获取当前日期、时间和时间戳&#xff0c;并且可以对时间进行格式化、计算和转换。 以下是一些常用的MySQL时间函数及其示例&#xff1a; 1、NOW()&#xff1a;用于获取当前…

网线制作(双绞线+水晶头)——T568B标准

参考视频&#xff1a;https://www.bilibili.com/video/BV1KQ4y1i7zP/ 1、使用剥线器 2、将线捋顺、排序、剪掉牵引线 记忆技巧 1.线序颜色整体是一浅一深 2.颜色顺序是黄、蓝、绿、棕 一个黄种人、从上向下看&#xff0c;分别看到的是蓝天、青草(绿)、泥土(棕色) 3.中间两根浅…

反序列化漏洞

概念 序列化&#xff08; serialization &#xff09;&#xff1a;讲数据结构、对象等状态转化成可使用的格式&#xff08;一般用于&#xff1a;缓存、网络发送、身份信息等&#xff09;&#xff0c;以备能够被还原为原始状态&#xff1b; 序列化 & 反序列化功能一般用作…

硬件产品经理

边端协调管理平台 主页一&#xff1a;模型管理1.1 边侧模型管理 二&#xff1a;配置管理2.1 终端软件配置管理 三&#xff1a;设备管理3.1 区域位置管理3.2 工控机管理&#xff08;其实就是围绕授权&#xff09;3.3 生产设备管理3.4 设备运行管理 四&#xff1a;数据服务4.1 实…

Unity 资源 之 风格化地形纹理(Stylized Terrain Textures)免费领取

风格化地形纹理&#xff1a;Stylized Terrain Textures 前言资源包内容领取兑换码 前言 亲爱的 Unity 游戏开发者们&#xff0c;我们自豪地为大家推荐最新的每周免费资源&#xff1a;风格化地形纹理&#xff01;这些令人惊叹的纹理将为你的游戏世界带来独特而引人入胜的视觉体…

MySQL与PostgreSQL关键对比三(索引类型)

目录 索引类型 B-tree 索引 Hash 索引 Full-text 索引 GiST 索引 GIN 索引 BRIN 索引 索引创建示例 MySQL PostgreSQL 结论 以下SQL语句的执行如果需要开发工具支持&#xff0c;可以尝试使用SQLynx或Navicat来执行。 MySQL和PostgreSQL在索引方面有许多相似之处&am…

layui左侧菜单栏,鼠标悬停显示菜单文字

layui封装的左侧菜单是固定宽度的&#xff0c;且左侧菜单栏在css里改变宽度&#xff0c;效果并不是很好&#xff08;还设计头部菜单栏&#xff09;&#xff0c;如果写js来让菜单栏能够拉伸&#xff0c;也比较麻烦&#xff0c;那怎么最简单的&#xff0c;让用户看到菜单的文字呢…

释放视频潜力:Topaz Video AI for mac/win 一款全新的视频增强与修复利器

在数字时代&#xff0c;视频已经成为我们记录生活、分享经历的重要方式。然而&#xff0c;有时候我们所拍摄的视频可能并不完美&#xff0c;可能存在模糊、噪点、抖动等问题。这时候&#xff0c;就需要一款强大的视频增强和修复工具来帮助我们提升视频质量&#xff0c;让它们更…

LabVIEW与Arm控制器之间的通讯

LabVIEW是一个强大的图形化编程环境&#xff0c;广泛应用于自动化控制、数据采集和测试测量等领域。而Arm控制器则是嵌入式系统中常用的处理器架构&#xff0c;广泛用于各种控制和计算任务。将LabVIEW与Arm控制器进行通讯控制&#xff0c;可以结合二者的优势&#xff0c;实现高…

推荐系统三十六式学习笔记:原理篇.近邻推荐07|人以群分,你是什么人就看到什么世界

目录 协同过滤基于用户的协同过滤背后的思想原理实践1、构造矩阵2、相似度计算3、推荐计算4、一些改进 应用场景&#xff1a;总结 谈及推荐系统&#xff0c;不得不说大名鼎鼎的协同过滤。协同过滤的重点在于协同&#xff0c;所谓协同&#xff0c;也就是群体互帮互助&#xff0c…

大模型安全技术实践 | RAG精确应对大模型敏感问题知识幻觉难题

一、引言 在大模型的实际应用落地过程中&#xff0c;会遇到所谓的幻觉&#xff08;Hallucination&#xff09;问题。对于语言模型而言&#xff0c;当生成的文本语法正确流畅&#xff0c;但与原文不符&#xff08;Faithfulness&#xff09;或事实不符&#xff08;Factualness&a…

Ubuntu 22.04安装cuda及Pytorch教程

文章目录 1、安装显卡驱动2、安装CUDA3、安装cuDNN4、安装pyTorch5、卸载CUDA参考资料 服务器重装系统后&#xff0c;需要重新安装显卡驱动、cuda及Pytorch等&#xff0c;有些步骤容易忘记&#xff0c;这里记录一下。这里我的服务器配置以及安装版本的情况如下&#xff1a; 服…

基于简单Agent对医疗数据进行分析

数据表 供应商资格审核规定.pdf 医生名录.xlsx 历史就诊记录.xlsx 患者信息名录.xlsx 药品.xlsx 药品库存管理.xlsx 采购单位基本信息.xlsx Agent测试 模型基于ChatGPT-3.5 问题&#xff1a;帮我找出不达标的供应商 Agent分析过程 [Thought: 0] Key Concepts: - 不达标的供…

IMX6ULL kernel移植

1.环境说明 编译主机Debian 12交叉编译工具arm-none-linux-gnueabihf-gcc(gcc version 12.3.1 20230626)kernel版本lf-6.6.3-1.0.02.官方默认版本说明 默认官方版本的kernel是可以运行的,直接按照下面的命令编译即可 ###清除掉默认配置make ARCH=arm CROSS_COMPILE=arm-no…

【每日刷题】Day58

【每日刷题】Day58 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c;​​​​​​​ 1. 3038. 相同分数的最大操作数目 I - 力扣&#xff08;LeetCode&#xff09; 2. 868. …

男士内裤怎么选?五款不能错过的超舒适男士内裤

在快节奏的现代都市生活中&#xff0c;男士们同样需要关注内在穿搭的品质与舒适度。一条优质贴身的男士内裤&#xff0c;不仅是日常穿着的舒适保障&#xff0c;更是展现男性精致品味的秘密武器。今天&#xff0c;就让我们一同探讨如何挑选出最适合自己的男士内裤&#xff0c;并…