redis中的分布式锁(setIfAbsent)(expire)

目录

应用场景

代码实例1:

代码实例2:

setIfAbsent:

expire:

举例说明:

代码实例3:

代码实例4:


还是一个同事问的一个问题,然后闲着没事就记录下来了。多人操作同一个保单,会出现数据不一致,所以呢,就准备为此单子加一个锁,所以就有了下面的代码。分享给大家

分布式锁的定义大家基本都很了解了,具体就是当需要在分布式环境中保证资源的互斥访问或一致性时,就可以考虑使用分布式锁。但需要注意的是,分布式锁虽然可以解决问题,但也会带来一定的性能开销和复杂度,因此在使用时需要权衡系统的性能和可维护性,以及使用分布式锁所带来的成本和风险。

应用场景

  1. 发任务调度:在分布式系统中,当需要对某个任务进行调度时,如果多个节点同时发起任务调度请求,可能会导致任务被多次执行。这时可以使用分布式锁来确保只有一个节点能够成功获取到任务调度的锁,从而避免任务的重复执行。
  2. 分布式事务:在分布式事务中,需要保证不同节点对共享资源的访问是互斥的,以防止数据不一致的问题。分布式锁可以用来保证在事务执行过程中,各个节点之间对共享资源的访问是互斥的。
  3. 分布式缓存:在分布式缓存中,如果多个节点同时对缓存进行访问和修改,可能会导致缓存中的数据不一致。这时可以使用分布式锁来确保各个节点对缓存的访问是互斥的。
  4. 购买限制:在电商等场景中,如果需要对某个商品的购买数量进行限制,当多个用户同时发起购买请求时,可以使用分布式锁来确保只有一个用户能够成功获取到购买锁,从而避免超卖等问题。

代码实例1:

redisTemplate.opsForValue().setIfAbsent("redisLock", uuid, 1000, TimeUnit.SECONDS);

这段代码是使用Spring Data Redis的RedisTemplate来执行一个Redis操作。具体来说,它尝试在Redis中设置一个键值对,但仅当该键不存在时。

详细解释如下:

  • "ruleRefreshLock":这是要设置的Redis键。
  • uuid:这是要设置的Redis值。
  • 1000:这是值的过期时间,单位是毫秒。
  • TimeUnit.SECONDS:这是过期时间的单位,这里是秒。

setIfAbsent方法的行为如下:

  • 如果键"ruleRefreshLock"在Redis中不存在,那么它会设置这个键的值为uuid,并给这个键设置一个1000秒的过期时间。此时,setIfAbsent方法返回true
  • 如果键"ruleRefreshLock"在Redis中已经存在,那么它不会做任何操作,并且setIfAbsent方法返回false

这个方法通常用于实现分布式锁。在这个例子中,你可能想要确保只有一个实例或线程能够获取到"ruleRefreshLock"这个锁。如果锁已经被其他实例或线程获取(即键已经存在),那么当前实例或线程就不会再尝试获取锁。如果锁未被获取(即键不存在),那么当前实例或线程就会获取锁,并设置一个过期时间以确保锁最终会被释放。

代码实例2:

设置KEY值过期时间

//假设 lockName 是你的锁的名称,expireTime 是你希望锁持续的时间(以分钟为单位)
redisTemplate.expire(lockName, expireTime, TimeUnit.MINUTES);

这段代码是使用 RedisTemplate 来设置 Redis 中某个键的过期时间。这与之前的 setIfAbsent 操作有所不同,主要区别如下:

setIfAbsent

  • 目的:尝试设置一个键值对,但仅当该键不存在时。
  • 返回值:如果键原本不存在且成功设置了键值对,返回 true;如果键已经存在,则不做任何操作并返回 false
  • 用途:通常用于实现分布式锁或其他需要原子性设置键值对的场景。

expire

  • 目的:为已存在的键设置或更新其过期时间。
  • 返回值:如果键存在,则成功设置或更新过期时间并返回 true;如果键不存在,则不进行任何操作并返回 false
  • 用途:通常用于确保存储在 Redis 中的数据在一段时间后被自动删除,以避免内存无限制增长。

举例说明:

假设你已经有了一个名为 lockName 的锁,并且这个锁已经被某个实例获取(即该键在 Redis 中已经存在)。你想让这个锁在一段时间后自动释放,那么你可以使用 expire 方法来设置锁的过期时间。

代码实例3:

redis版本        spring-data-redis-2.7.10.jar

@Slf4j
@Component
public class redisSchedule implements SchedulingConfigurer  {@Value("${rule.limit.cron}")private String cron;@Value("${schedule.rule}")private String scheduleRule;@Autowiredprivate StringRedisTemplate redisTemplate;@Overridepublic void configureTasks(ScheduledTaskRegistrar taskRegistrar) {taskRegistrar.addCronTask(() -> {// 分布式锁,集群环境只允许一台服务修改定时任务String uuid = UUID.randomUUID().toString();Boolean bool = redisTemplate.opsForValue().setIfAbsent("redisLock", uuid, 1000, TimeUnit.SECONDS);try {if (bool) {//逻辑代码}} catch (Exception e) {log.error(e.getMessage());} finally {//  释放锁,先比对自己锁的值是否相等,相等则为自己的锁String script = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";redisTemplate.execute(new DefaultRedisScript<Long>(script, Long.class), Arrays.asList("redisLock"), uuid);}}, cron);}
}

代码实例4:

redis版本        spring-data-redis-1.8.0.RELEASE.jar

//锁的过期时间,默认为5分钟
private Long expireTime = 5L;try {//多个执行任务去获得锁,如果没有获取证明还有任务在执行中,那么将不再执行任务Boolean isLock = redisTemplate.opsForValue().setIfAbsent(lockName, "lock");if (isLock){//获取到锁,那么设置过期时间,防止死锁this.redisTemplate.expire(lockName, expireTime, TimeUnit.MINUTES);//逻辑代码}else {logger.info("任务执行锁定失败,Lock被占用,当前分片:=====");throw new Exception("任务执行锁定失败");}} catch (Exception e) {e.printStackTrace();throw new Exception(e.getMessage());}

总结一下,setIfAbsent 用于在键不存在时设置键值对,并返回操作是否成功的布尔值;而 expire 用于设置或更新已存在键的过期时间,并返回操作是否成功的布尔值。这两个操作经常一起使用来实现分布式锁,其中 setIfAbsent 用于尝试获取锁,而 expire 用于设置锁的过期时间以确保锁最终会被释放。两种方式的用法看对应的应用场景来使用

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

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

相关文章

全网最详细的接口自动化测试框架实战(Pytest+Allure+Excel)

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号【互联网杂货铺】&#xff0c;回复 1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 1. Allure 简介 Allure 框架是一个灵活的、轻量级的、支持多语…

k8s service的概念以及创建方法

Service 的功能&#xff1a; Service主要用于提供网络服务&#xff0c;通过Service的定义&#xff0c;能够为客户端应用提供稳定的访问地址&#xff08;域名或IP地址&#xff09;和负载均衡功能&#xff0c;以及屏蔽后端Endpoint的变化&#xff0c;是K8s实现微服务的核心资源。…

react-JSX基本使用

1.目标 能够知道什么是JSX 能够使用JSX创建React元素 能够在JSX中使用JS表达式 能够使用JSX的条件渲染和列表渲染 能够给JSX添加样式 2.目录 JSX的基本使用 JSX中使用JS表达式 JSX的条件渲染 JSX的列表渲染 JSX的样式处理 3.JSX的基本使用 3.1 createElement()的问题 A. …

在Node.js中如何实现用户身份验证和授权

当涉及到构建安全的应用程序时&#xff0c;用户身份验证和授权是至关重要的一环。在Node.js中&#xff0c;我们可以利用一些流行的库和技术来实现这些功能&#xff0c;确保我们的应用程序具有所需的安全性。本篇博客将介绍如何在Node.js中实现用户身份验证和授权。 用户身份验…

“智农”-大棚可视化

基于自主可控的数字孪生技术、物联网技术、大数据技术&#xff0c;构建全流程的新型农业一体化管理平台&#xff0c;围绕产运销管理全流程&#xff0c;实现生产->存储->包装->运输->销售的全链条管理。融合农业数据管理、农业数据预警显示、多维数据综合显示、农产…

Jvm之内存泄漏

1 内存溢出 1.1 概念 java.lang.OutOfMemoryError&#xff0c;是指程序在申请内存时&#xff0c;没有足够的内存空间供其使用&#xff0c;出现OutOfMemoryError。产生该错误的原因主要包括&#xff1a;JVM内存过小。程序不严密&#xff0c;产生了过多的垃圾。 程序体现: 内…

微服务架构 SpringCloud

单体应用架构 将项目所有模块(功能)打成jar或者war&#xff0c;然后部署一个进程--医院挂号系统&#xff1b; > 优点: > 1:部署简单:由于是完整的结构体&#xff0c;可以直接部署在一个服务器上即可。 > 2:技术单一:项目不需要复杂的技术栈&#xff0c;往往一套熟悉的…

LabVIEW水下温盐深数据一体化采集与分析

LabVIEW水下温盐深数据一体化采集与分析 开发一个基于LabVIEW的水下温盐深数据一体化采集与分析系统&#xff0c;实现海洋环境监测的自动化和精确化。通过集成温度、盐度和深度传感器&#xff0c;结合USB数据采集卡&#xff0c;利用LabVIEW软件开发的图形化界面&#xff0c;实…

腾讯云服务器4核8G性能,和阿里云比怎么样?

腾讯云4核8G服务器支持多少人在线访问&#xff1f;支持25人同时访问。实际上程序效率不同支持人数在线人数不同&#xff0c;公网带宽也是影响4核8G服务器并发数的一大因素&#xff0c;假设公网带宽太小&#xff0c;流量直接卡在入口&#xff0c;4核8G配置的CPU内存也会造成计算…

这波知识点分享可得接稳了!非线性模型线性化方法技巧!

现在电力系统优化方向的文章几乎都要提及将非线性模型线性化&#xff0c;使用的方法大致可包括分段线性化&#xff08;最基础&#xff09;&#xff0c;混合整数线性化方法&#xff0c;绝对值法&#xff0c;大M方法&#xff0c;关于非线性模型线性化方法的文章和推文介绍也数不胜…

JAVA AQS源码深度讲解和分析

为方便理解&#xff0c;本文章以非公平锁ReentrantLock()为例作为突破讲解方法lock。 前置知识&#xff1a;JAVA AQS源码分析前置知识-CSDN博客 ReentrantLock的原理 Lock接口的实现类&#xff0c;基本都是通过聚合了一个队列同步器的子类完成线程访问控制的 从最简单的lock方…

C语言————结构体

接下来我们来了解C语言中很重要的内容&#xff1a;结构体。虽然到现在我们可以创建常量&#xff0c;变量&#xff0c;数组&#xff0c;但是存储的都是相同类型的数据&#xff0c;如果我们需要写入不同数据类型的信息怎么办&#xff0c;例如常见的身份证上的信息&#xff0c;有身…

springboot+vue+mysql+easyexcel实现文件导出+导出的excel单元格添加下拉列表

Excel导出 EasyExcel官方文档 官方文档本身写的非常详细&#xff0c;我就是根据官方文档内的写Excel里web中的写实现的导出 后端 对象 需要写一个实体类 其中涉及到一些用到的EasyExcel的注解 ColumnWidth(20) 列宽设为20&#xff0c;自定义的&#xff0c;放在实体类上面是…

JavaWeb——005 -- 请求响应 分层解耦(Postman、三层架构、IOC、DI、注解)

目录 一、请求 1、Postman&#xff08;接口测试工具&#xff09; 1.1、介绍 ②、安装 2、简单参数 1.1、原始方式 1.2、SpringBoot方法 ③、小结 3、实体参数 3.1、简单实体对象 3.2、复杂实体对象 3.3、小结 4、数组集合参数 ①、数组​编辑 ②、集合 ③、小结…

Alist访问主页显示空白解决方法

文章目录 问题记录问题探索和解决网络方案问题探究脚本内容查看 最终解决教程 问题记录 访问Alist主页显示空白&#xff0c;按F12打开开发人员工具 ,选择控制台&#xff0c;报错如下 index.75e31196.js:20 Uncaught TypeError: Cannot assign to read only property __symbo…

python|闲谈2048小游戏和数组的旋转及翻转和转置

目录 2048 生成数组 n阶方阵 方阵旋转 顺时针旋转 逆时针旋转 mxn矩阵 矩阵旋转 测试代码 测试结果 翻转和转置 2048 《2048》是一款比较流行​的数字游戏​&#xff0c;最早于2014年3月20日发行。原版2048由Gabriele Cirulli首先在GitHub上发布&#xff0c;后被移…

【Day59】代码随想录之动态规划_583两个字符串的删除操作_72编辑距离

文章目录 动态规划理论基础动规五部曲&#xff1a;出现结果不正确&#xff1a; 1. 583两个字符串的删除操作2. 72编辑距离 动态规划理论基础 动规五部曲&#xff1a; 确定dp数组 下标及dp[i] 的含义。递推公式&#xff1a;比如斐波那契数列 dp[i] dp[i-1] dp[i-2]。初始化d…

选择排序的简单介绍

选择排序是一种简单直观的排序算法&#xff0c;其原理如下&#xff1a; 1. 遍历数组&#xff0c;找到最小&#xff08;或最大&#xff09;的元素&#xff0c;并将其与数组的第一个元素交换位置。 2. 接着在剩下的元素中找到最小&#xff08;或最大&#xff09;的元素&#xff…

园区水费收费管理系统

园区水费收费管理系统是专为园区或小区的水费管理而设计的系统&#xff0c;旨在提高水费收费效率、精准监测水费使用情况&#xff0c;简化管理流程&#xff0c;为园区管理方和居民提供便捷、高效的水费管理解决方案。该系统结合了数字化技术和智能化管理手段&#xff0c;通过线…

动态规划-状态转移(O(n))

获取生成数组中的最大值 1.题目 2.思路 其实只要看透该题的本质 并不难&#xff0c;应用动态规划&#xff0c;题目就已经给出了状态方程的式子。 首先规定好maxn的大小&#xff0c;防止溢出。定义nums数组。定义一个函数&#xff0c;写入状态方程式子。最后定义一个变量与数…