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

news2024/11/17 21:43:56

目录

应用场景

代码实例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;
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public 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.coloradmin.cn/o/1476343.html

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

相关文章

(Linux学习二)文件管理基础操作命令笔记

Linux目录结构&#xff1a; bin 二进制文件 boot 启动目录 home 普通用户 root 超管 tmp 临时文件 run 临时运行数据 var 日志 usr 应用程序、文件 etc 配置文件 dev 文件系统 一、基础操作 在 Linux 终端中&#xff0c;你可以使用以下命令来清屏&#xff1a; clear 命令&am…

ubuntu2204部署hbase2.3.7

开启root 修改root用户的密码 sudo passwd rootSSH放行 sudo sed -i s/^#\?PermitRootLogin.*/PermitRootLogin yes/g /etc/ssh/sshd_config; sudo sed -i s/^#\?PasswordAuthentication.*/PasswordAuthentication yes/g /etc/ssh/sshd_config;重启服务 sudo service ssh…

IDEA利用鼠标调整字体大小

就可以按住ctrl和鼠标调节代码字体的大小啦&#xff01; 如果有用&#xff0c;记得给我来个赞~ 谢啦&#xff01;

什么是生成式人工智能?

近年来&#xff0c;人工智能取得了重大进展&#xff0c;其中发展迅速的领域之一就是生成式人工智能。生成式人工智能是人工智能和深度学习的一个子领域&#xff0c;主要使用机器学习技 术根据现有数据训练算法和模型&#xff0c;生成诸如图像、文本、音乐、视频等新内容。 要更…

nginx 反向代理 与缓存功能

一 理论说明 &#xff08;一&#xff09;反向代理简介 反向代理&#xff1a;reverse proxy&#xff0c;指的是代理外网用户的请求到内部的指定的服务器&#xff0c;并将数据返回给用户的一种方式&#xff0c;这是用的比较多的一种方式。 即 代理服务机 Nginx 除了可以在企…

linux系统-----------搭建LNMP 架构

PHP(Hypertext Preprocessor 超文本预处理器)是通用服务器端脚本编程语言&#xff0c;主要用于web开发实现动态web页面&#xff0c;也是最早实现将脚本嵌入HTML源码文档中的服务器端脚本语言之一。同时&#xff0c;php还提供了一个命令行接口&#xff0c;因此&#xff0c;其也可…

如何使用便签快速分类工作待办事项

在日常工作和生活中&#xff0c;我们经常需要处理各种各样的待办事项。而有效地分类这些任务&#xff0c;可以帮助我们更好地管理时间和提高工作效率。使用便签是一种简单而实用的方法&#xff0c;下面将介绍如何利用好用便签来快速分类工作待办事项。 首先&#xff0c;你可以…

软考中级1(数据库系统工程师)

1.程序计数器 保存待读取指令的地址 累加器 保存原操作数和结果 2.DMA方式不需要CPU&#xff0c;由DMA控制器直接控制数据的传送 3.数据位n位&#xff0c;校验位k位&#xff0c;海明码满足的关系&#xff1a;2^k-1>nk 4.高速缓存Cache&#xff1a;位于CPU和主…

大数据分布式计算工具Spark实战讲解

PySpark 什么是PySpark&#xff1f; Spark是Apache基金会旗下的顶级开源项目&#xff0c;用于对海量数据进行大规模分布式计算。 PySpark是Spark的Python实现&#xff0c;是Spark为Python开发者提供的编程入口&#xff0c;用于以Python代码完成Spark任务的开发 PySpark不仅可…

三天学会阿里分布式事务框架Seata-SpringCloud Alibaba分布式基础案例搭建

锋哥原创的分布式事务框架Seata视频教程&#xff1a; 实战阿里分布式事务框架Seata视频教程&#xff08;无废话&#xff0c;通俗易懂版&#xff09;_哔哩哔哩_bilibili实战阿里分布式事务框架Seata视频教程&#xff08;无废话&#xff0c;通俗易懂版&#xff09;共计10条视频&…

记录工作中遇见问题、学习项

1、判空操作 Demo demo Optional .ofNullable(demoService.getById(id)) .orElseThrow(() -> new ServiceException("不存在id为" id "的数据")); 2、SQL方面 1、group by : GROUP BY 子句必须放在 WHERE 子句中的条件之后&#…

网络:IPv6

1、由于IPv4地址资源枯竭&#xff0c;所以产生了IPV6。 版本长度地址数量IPv432 bit4 294 967 296IPv6128 bit340 282 366 920 938 463 374 607 431 768 211 456 2、IPv6的基本报头在IPv4报头基础上&#xff0c;增加了流标签域&#xff0c;去除了一些冗余字段&#xff0c;使报…

Apache SeaTunnel 及 Web 功能部署指南(小白版)

在大数据处理领域&#xff0c;Apache SeaTunnel 已成为一款备受青睐的开源数据集成平台&#xff0c;它不仅可以基于Apache Spark和Flink&#xff0c;而且还有社区单独开发专属数据集成的Zeta引擎&#xff0c;提供了强大的数据处理能力。随着SeaTunnel Web的推出&#xff0c;用户…

Python异步IO库之uvloop使用详解

概要 在Python中,异步编程已经成为处理高并发和IO密集型任务的主要方式之一。而uvloop库则是一个专门针对异步IO操作进行优化的库,它能够显著提高异步程序的性能。本文将深入探讨uvloop库的使用方法、功能特性以及如何利用它来加速异步IO编程。 什么是uvloop库? uvloop是一…

探讨:围绕 props 阐述 React 通信

在 ✓ &#x1f1e8;&#x1f1f3; 开篇&#xff1a;通过 state 阐述 React 渲染 中&#xff0c;以 setInterval 为例&#xff0c;梳理了 React 渲染的相关内容。 &#x1f4e2; 本篇会 ✓ &#x1f1e8;&#x1f1f3; 围绕 props 阐述 React 通信 props React 组件使用 pro…

存储xss实现获取cookie(本地实战)

实战更能体验收获&#xff01;&#xff01;&#xff01; 环境准备&#xff1a; 1.phpstudy 2.dvwa靶场 实战 首先我们在phpstudy指定的localhost网站目录下编写一个xss.php文件&#xff0c;内容如下&#xff1a; <?php $cookie $_GET[cookie]; $ip getenv (REMOTE_…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的活体人脸检测系统(Python+PySide6界面+训练代码)

摘要&#xff1a;本篇博客详细讲述了如何利用深度学习构建一个活体人脸检测系统&#xff0c;并且提供了完整的实现代码。该系统基于强大的YOLOv8算法&#xff0c;并进行了与前代算法YOLOv7、YOLOv6、YOLOv5的细致对比&#xff0c;展示了其在图像、视频、实时视频流和批量文件处…

找出异常点 python

统计学方法 zscore 原理&#xff1a; Z-score 基于正态分布理论&#xff0c;它量化了数据点距离数据集平均值的相对标准偏差。 通常&#xff0c;如果 Z-score 的绝对值超过某个阈值&#xff08;如3或更大&#xff09;&#xff0c;该数据点就被认为是异常值。这是因为正态分布下…

【Spring】模拟 Spring 框架

Spring IoC 容器的实现原理&#xff1a;工厂模式 解析XML 反射机制 我们给自己的框架起名为&#xff1a;mySpring&#xff08;我的春天&#xff09; 一、创建 mySpring 模块 引入dom4j 和 jaxen 的依赖&#xff0c;因为要使用它解析XML文件&#xff0c;还有 junit 依赖 &l…

【MATLAB】SVMD_ MFE_SVM_LSTM 神经网络时序预测算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~也可转原文链接获取~ 1 基本定义 SVMD_MFE_SVM_LSTM神经网络时序预测算法结合了单变量分解&#xff08;SVMD&#xff09;、多尺度特征提取&#xff08;MFE&#xff09;、聚类后展开支持向量机&#xff08;SVM&#xff09;…