Redisson分布式锁(超时释放及锁续期)

news2025/3/29 5:57:45

🍓 简介:java系列技术分享(👉持续更新中…🔥)
🍓 初衷:一起学习、一起进步、坚持不懈
🍓 如果文章内容有误与您的想法不一致,欢迎大家在评论区指正🙏
🍓 希望这篇文章对你有所帮助,欢迎点赞 👍 收藏 ⭐留言 📝

🍓 更多文章请点击
在这里插入图片描述在这里插入图片描述

文章目录

  • 一、分布式锁简介
  • 二、为什么用分布式锁?
  • 三、分布式锁应该具备哪些条件
  • 四、Redis实现分布式锁如何防止死锁?
  • 五、Redis实现分布式锁如何合理的控制锁的有效时长?
  • 六、Redisson使用步骤
    • 6.1 引入依赖
    • 6.2 定义配置类
      • 6.2.1 单机redis
      • 6.2.2 集群redis
    • 6.3 分布式锁工具类(两种获取锁方式)
    • 6.4 业务代码加入分布式锁

一、分布式锁简介

分布式锁 是一种用于分布式系统中协调多个节点对共享资源进行互斥访问的机制。它确保在同一时间只有一个节点可以执行某个操作或访问某个资源,从而避免数据不一致或冲突。

概述 :在分布式系统中,多个线程访问共享数据就会出现数据安全性的问题。而由于jdk中的锁要求多个线程在同一个jvm中,因此在分布式系统中无法使用jdk中的锁保证数据的安全性,那么此时就需要使用分布式锁。

二、为什么用分布式锁?

作用 :可以保证在分布式系统中多个线程访问共享数据时数据的安全性

  1. 资源互斥访问:确保多个节点或进程在访问共享资源时不会发生冲突。
  2. 避免重复操作:防止同一任务被多个节点重复执行。
  3. 数据一致性:在分布式系统中,确保数据的一致性和完整性。
  4. 任务调度:在分布式任务调度系统中,确保任务不会被多个节点同时执行(例如:定时任务)。

三、分布式锁应该具备哪些条件

  1. 在分布式系统环境下,一个方法在同一时间只能被一个机器的一个线程执行
  2. 高可用的获取锁与释放锁
  3. 高性能的获取锁与释放锁
  4. 具备可重入特性
  5. 具备锁失效机制,防止死锁

四、Redis实现分布式锁如何防止死锁?

产生死锁的原因:如果一个客户端持有锁的期间突然崩溃了,就会导致无法解锁,最后导致出现死锁的现象。
所以要有个超时的机制,在设置key的值时,需要加上有效时间,如果有效时间过期了,就会自动失效,就不会出现死锁。

五、Redis实现分布式锁如何合理的控制锁的有效时长?

有效时间设置多长,假如我的业务操作比有效时间长?我的业务代码还没执行完就自动给我解锁了,不就废废了吗。

锁续期实现思路: 当加锁成功后,同时开启守护线程,默认有效期是用户所设置的,然后默认每隔10秒就会给锁续期到用户所设置的有效期(可以修改),只要持有锁的客户端没有宕机,就能保证一直持有锁,直到业务代码执行完毕自己解锁,如果宕机了自然就在有效期失效后自动解锁。

这些都可以通过以使用redis官方所提供的Redisson进行实现。

六、Redisson使用步骤

6.1 引入依赖

<dependency>
     <groupId>org.redisson</groupId>
     <artifactId>redisson-spring-boot-starter</artifactId>
     <version>3.34.1</version>
     <exclusions>
         <exclusion>
             <groupId>org.redisson</groupId>
             <artifactId>redisson-spring-data-33</artifactId>
         </exclusion>
     </exclusions>
 </dependency>

 <dependency>
     <groupId>org.redisson</groupId>
     <artifactId>redisson-spring-data-23</artifactId>
     <version>3.34.1</version>
 </dependency>

6.2 定义配置类

6.2.1 单机redis

spring:
  redis:
    host: 192.168.1.0
    port: 6379
    password: abcdefghijk
    database: 1
@Configuration
public class RedissonConfig {

    @Value("${spring.redis.port}")
    private String port;
    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.password}")
    private String password;
    @Value("${spring.redis.database}")
    private Integer database;

    @Bean
    public RedissonClient redissonClient(){
        Config config = new Config();
        //这边采用了【单节点模式】 - redis地址
        config.useSingleServer().setAddress("redis://"+host+":"+port).setPassword(password).setDatabase(database);
        //根据config创建出RedissonClient的实列
        RedissonClient redissonClient = Redisson.create(config);
        return redissonClient;
    }
}

6.2.2 集群redis

spring:
  redis:
    timeout: 6000ms
    database: 0
    password: abcdefghijk           #密码,若没有,不填写
    cluster:
      nodes: #集群ip+端口号
        - 192.168.1.1:6379
        - 192.168.1.2:6380
        - 192.168.1.3:6381
        - 192.168.1.4:6382
        - 192.168.1.5:6383
        - 192.168.1.6:6384
        - 192.168.1.7:6385
@Configuration
public class RedissonConfig {

    @Autowired
    private RedisProperties redisProperties;


    @Bean
    public RedissonClient redissonClient() throws IOException {
        Config config = new Config();
        if (redisProperties.getCluster() != null) {
            //集群模式配置
            List<String> urls = redisProperties.getCluster().getNodes();

            String[] clusterNodes  = urls.toArray(new String[urls.size()]);
            for (int i = 0; i < clusterNodes.length; i++) {
                clusterNodes[i] = "redis://" + clusterNodes[i];
            }
            ClusterServersConfig clusterServersConfig = config.useClusterServers()
                    .addNodeAddress(clusterNodes);
            if (StrUtil.isNotBlank(redisProperties.getPassword())) {
                clusterServersConfig.setPassword(redisProperties.getPassword());
            }
        } else {
            //单节点配置
            String address = "redis://" + redisProperties.getHost() + ":" + redisProperties.getPort();
            SingleServerConfig serverConfig = config.useSingleServer();
            serverConfig.setAddress(address);
            if (StrUtil.isNotBlank(redisProperties.getPassword())) {
                serverConfig.setPassword(redisProperties.getPassword());
            }
            serverConfig.setDatabase(redisProperties.getDatabase());
        }
        config.setLockWatchdogTimeout(15000);
        return Redisson.create(config);
    }
}

6.3 分布式锁工具类(两种获取锁方式)

@Component
@Slf4j
public class RedissonLockUtil {
    @Autowired
    private RedissonClient redissonClient;

    /**
     * 获取分布式锁(如果业务逻辑执行时间不确定,或者可能较长,建议启用看门狗机制。)
     *
     * @param name      锁的key值
     * @param waitTime  获取锁的最大等待时间
     * @param unit      时间单位
     * @return true: 获取到锁, false: 没有获取到锁
     */
    public boolean getLock(String name, long waitTime,  TimeUnit unit) throws InterruptedException {
        RLock lock = redissonClient.getLock(name);
        //没有设置锁释放时间 看门狗机制会自动续期锁的租约时间,避免锁提前释放。锁会在租约时间后自动释放,避免死锁。
        boolean succeed = lock.tryLock(waitTime, unit);
        return succeed;
    }

    /**
     * 获取分布式锁 (如果业务逻辑执行时间较短且可控,可以显式设置 leaseTime,避免看门狗机制的开销)
     * @param name      锁的key值
     * @param waitTime  获取锁的最大等待时间
     * @param leaseTime 锁的自动释放时间(超时释放)
     * @param unit      时间单位
     * @return true: 获取到锁, false: 没有获取到锁
     */
    public boolean getLock(String name, long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {
        RLock lock = redissonClient.getLock(name);
        boolean succeed = lock.tryLock(waitTime, leaseTime, unit);
        return succeed;
    }

    /**
     *  解锁分布式锁
     * @param name     锁key值
     */
    public void unLock(String name){
        RLock lock = redissonClient.getLock(name);
        lock.unlock();
    }
}

6.4 业务代码加入分布式锁

public void executeInternal(JobExecutionContext jobExecutionContext) {
    boolean lock = false;
    try {
        lock = redissonLockUtil .getLock(ZNJ_COCKPIT_TECH_TRAINING_JOB, 5, 10, TimeUnit.SECONDS);
        if (lock){
            log.info("=====================[获取锁,正式开始业务逻辑]============");
            //赋能模块表同步
            //业务逻辑
            log.info("====================[释放锁,业务逻辑执行结束]============");
        }
    } catch (Exception e) {
        log.error("获取锁失败:e:{}",e.getMessage());
    } finally {
        redisUtils.unLock(ZNJ_COCKPIT_TECH_TRAINING_JOB);
    }
    log.info("=====================[end]================= lock:{}",lock);
}

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

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

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

相关文章

音视频学习(三十):fmp4

FMP4&#xff08;Fragmented MP4&#xff09;是 MP4&#xff08;MPEG-4 Part 14&#xff09;的扩展版本&#xff0c;它支持流式传输&#xff0c;并被广泛应用于DASH&#xff08;Dynamic Adaptive Streaming over HTTP&#xff09;和HLS&#xff08;HTTP Live Streaming&#xf…

Java安全-类的动态加载

类的加载过程 先在方法区找class信息&#xff0c;有的话直接调用&#xff0c;没有的话则使用类加载器加载到方法区(静态成员放在静态区&#xff0c;非静态成功放在非静态区)&#xff0c;静态代码块在类加载时自动执行代码&#xff0c;非静态的不执行;先父类后子类&#xff0c;…

内存取证之windows-Volatility 3

一&#xff0c;Volatility 3下载 1.安装Volatility 3。 要求&#xff1a;python3.7以上的版本&#xff0c;我的是3,11&#xff0c;这里不说python的安装方法 使用 pip 安装 Volatility 3&#xff1a; pip install volatility3 安装完成后&#xff0c;验证安装&#xff1a; v…

fastapi+playwright爬取google搜索1-3页的关键词返回json

1,playwright无头 2,代理池随机获取代理ip 3,随机浏览行为,随机页面滚动 4,启用stealth模式 5,随机延时搜索 from fastapi import FastAPI, HTTPException from fastapi.responses import JSONResponse import asyncio from concurrent.futures import ThreadPool…

阿里云对象存储教程

搜“对象存储->免费试用” 选择你的心仪产品&#xff0c;我使用的是第一个 创建后获得三个实例&#xff1a; 点击右上角自己的账号可以进入到AccessKey管理界面 回到对象存储控制台创建Bucket实例 在以下文件中替换自己Bucket的信息即可美美使用~ package com.kitty.blog…

【Node.js入门笔记10---http 模块】

Node.js入门笔记10 Node.js---http 模块一、核心功能0.学习http的前提1. 创建 HTTP 服务器2. 处理请求和响应 二、进阶用法1. 路由管理2. 处理 POST 请求3. 中间件模式 三、常见场景四、错误处理与安全五、对比 http 与 Express六、工具库推荐&#xff1a; Node.js—http 模块 …

实验11 机器学习-贝叶斯分类器

实验11 机器学习-贝叶斯分类器 一、实验目的 &#xff08;1&#xff09;理解并熟悉贝叶斯分类器的思想和原理&#xff1b; &#xff08;2&#xff09;熟悉贝叶斯分类器的数学推导过程&#xff1b; &#xff08;3&#xff09;能运用贝叶斯分类器解决实际问题并体会算法的效果&a…

OpenHarmony子系统开发 - 电池管理(二)

OpenHarmony子系统开发 - 电池管理&#xff08;二&#xff09; 五、充电限流限压定制开发指导 概述 简介 OpenHarmony默认提供了充电限流限压的特性。在对终端设备进行充电时&#xff0c;由于环境影响&#xff0c;可能会导致电池温度过高&#xff0c;因此需要对充电电流或电…

hive 数据简介

Hive介绍 1&#xff09;Hive简介 Hive是基于Hadoop的一个数据仓库工具&#xff0c;用于结构化数据的查询、分析和汇总。Hive提供类SQL查询功能&#xff0c;它将SQL转换为MapReduce程序。 Hive不支持OLTP&#xff0c;Hive无法提供实时查询。 2&#xff09;Hive在大数据生态环境…

Win32桌面编程:ACLUI.DLL,EditSecurity(IntPtr hwndOwner, ISecurityInformation psi)

在Windows编程中&#xff0c;我们通常需要借助通用对话框的力量&#xff0c;今天我们就聊一下“安全属性表”通用对话框的使用心得。 当我们调用EditSecurity函数时&#xff1a; 1.EditSecurity将调用ISecurityInformation中的GetObjectInformation函数 在编写 ISecurityInf…

数据分析异步进阶:aiohttp与Asyncio性能提升

一、时间轴呈现方案进程 2023-04-01&#xff1a;需求确认 确定目标&#xff1a;使用aiohttp与Asyncio提升采集性能&#xff0c;目标采集今日头条网站的新闻数据&#xff08;标题、内容、时间等&#xff09;。同时要求在程序中加入代理IP、Cookie和UserAgent的设置&#xff0c;…

《AI大模型趣味实战 》第8集:多端适配 个人新闻头条 基于大模型和RSS聚合打造个人新闻电台(Flask WEB版) 2

《AI大模型趣味实战 》第8集&#xff1a;多端适配 个人新闻头条 基于大模型和RSS聚合打造个人新闻电台(Flask WEB版) 2 摘要 本文末尾介绍了如何实现新闻智能体的方法。在信息爆炸的时代&#xff0c;如何高效获取和筛选感兴趣的新闻内容成为一个现实问题。本文将带领读者通过P…

低配电脑畅玩《怪物猎人:荒野》,ToDesk云电脑优化从30帧到144帧?

《怪物猎人&#xff1a;荒野&#xff08;Monster Hunter Wilds&#xff09;》自2025年正式发售以来已取得相当亮眼的成绩&#xff0c;仅用三天时间便轻松突破800万销量&#xff0c;目前顺利蝉联周榜冠军&#xff1b;凭借着开放世界的宏大场景和丰富的狩猎玩法&#xff0c;该游戏…

【js逆向入门】图灵爬虫练习平台 第九题

地址&#xff1a;aHR0cHM6Ly9zdHUudHVsaW5ncHl0b24uY24vcHJvYmxlbS1kZXRhaWwvOS8 f12进入了debugger&#xff0c;右击选择一律不在此处暂停&#xff0c; 点击继续执行 查看请求信息 查看载荷&#xff0c;2个加密参数&#xff0c;m和tt 查看启动器&#xff0c;打上断点 进来 往…

NET6 WebApi第5讲:中间件(源码理解,俄罗斯套娃怎么来的?);Web 服务器 (Nginx / IIS / Kestrel)、WSL、SSL/TSL

一、NET6的启动流程 区别&#xff1a; .NET6 WebApi第1讲&#xff1a;VSCode开发.NET项目、区别.NET5框架【两个框架启动流程详解】_vscode webapi-CSDN博客 2、WebApplicationBuilder&#xff1a;是NET6引入的一个类&#xff0c;是建造者模式的典型应用 1>建造者模式的…

Nginx及前端部署全流程:初始化配置到生产环境部署(附Nginx常用命令)

nginx&前端从初始化配置到部署&#xff08;xshell&#xff09; 前言下载nginx前端打包与创建具体文件夹路径配置nginx.nginx.conf文件配置项内容 配置nginx.service文件配置项内容 启动nginx常用nginx命令 前言 目标&#xff1a;在xshell中部署前端包。 第一步&#xff1a…

python 实现一个简单的window 任务管理器

import tkinter as tk from tkinter import ttk import psutil# 运行此代码前&#xff0c;请确保已经安装了 psutil 库&#xff0c;可以使用 pip install psutil 进行安装。 # 由于获取进程信息可能会受到权限限制&#xff0c;某些进程的信息可能无法获取&#xff0c;代码中已经…

【xiaozhi赎回之路-2:语音可以自己配置就是用GPT本地API】

固件作用 打通了网络和硬件的沟通 修改固件实现【改变连接到小智服务器的】 回答逻辑LLM自定义 自定义了Coze&#xff08;比较高级&#xff0c;自定义程度比较高&#xff0c;包括知识库&#xff0c;虚拟脚色-恋人-雅思老师-娃娃玩具{可能需要使用显卡对开源模型进行微调-产…

WX小程序

下载 package com.sky.utils;import com.alibaba.fastjson.JSONObject; import org.apache.http.NameValuePair; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.Cl…

Spring boot 3.4 后 SDK 升级,暨 UI API/MCP 计划

PS 写这篇文章后看到 A Deep Dive Into MCP and the Future of AI Tooling | Andreessen HorowitzWe explore what MCP is, how it changes the way AI interacts with tools, what developers are already building, and the challenges that still need solving. https://a1…