原生redis实现分布式锁

原生 Redis(Jedis、Lettuce) 实现分布式锁,可以参考 Redisson 的原理,但需要自己处理锁的自动续期、故障恢复等细节。核心思路是使用 Redis 的 SET NX EXSET PX NX 命令来实现互斥锁,并利用 Lua 脚本 保障原子性。

实现思路

  • 获取锁
    • SET key value NX PX expiration,确保锁只能被一个线程获取,并设置过期时间。
  • 自动续期
    • 通过 后台线程 定时续期,防止业务执行时间过长导致锁超时释放。
  • 释放锁
    • 通过 Lua 脚本 保证原子性,只有 当前线程 持有锁时才能释放。

完整代码

1. 依赖引入

使用 Jedis 作为 Redis 客户端:

<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>4.3.1</version>
</dependency>

2. 分布式锁实现

获取锁
import redis.clients.jedis.Jedis;
import java.util.UUID;public class RedisLock {private static final String LOCK_SUCCESS = "OK";private static final String LOCK_KEY = "my_lock";private static final int EXPIRE_TIME = 10_000; // 10秒过期private final Jedis jedis;private final String lockValue; // 唯一标识锁的持有者public RedisLock(Jedis jedis) {this.jedis = jedis;this.lockValue = UUID.randomUUID().toString(); // 防止误删}public boolean tryLock() {String result = jedis.set(LOCK_KEY, lockValue, "NX", "PX", EXPIRE_TIME);return LOCK_SUCCESS.equals(result); // 返回 true 代表加锁成功}
}
自动续期

如果业务执行时间超过 10s,锁会自动释放,所以需要定时续期

import java.util.concurrent.*;public class LockRenewal {private static final int RENEWAL_INTERVAL = 5000; // 每5秒续期private final Jedis jedis;private final String lockValue;private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);public LockRenewal(Jedis jedis, String lockValue) {this.jedis = jedis;this.lockValue = lockValue;}public void startRenewal() {scheduler.scheduleAtFixedRate(() -> {if (lockValue.equals(jedis.get("my_lock"))) {jedis.pexpire("my_lock", 10_000);}}, 0, RENEWAL_INTERVAL, TimeUnit.MILLISECONDS);}public void stopRenewal() {scheduler.shutdown();}
}
释放锁

使用 Lua 脚本,确保只有 持有锁的线程 才能删除:

public void unlock() {String luaScript ="if redis.call('get', KEYS[1]) == ARGV[1] then " +"   return redis.call('del', KEYS[1]) " +"else " +"   return 0 " +"end";jedis.eval(luaScript, 1, "my_lock", lockValue);
}

3. 使用示例

Jedis jedis = new Jedis("localhost", 6379);
RedisLock redisLock = new RedisLock(jedis);
LockRenewal renewal = new LockRenewal(jedis, redisLock.lockValue);if (redisLock.tryLock()) {renewal.startRenewal(); // 开启自动续期try {// 执行业务逻辑System.out.println("获取到锁,执行业务...");Thread.sleep(15000); // 模拟业务执行时间超过锁的原始超时时间} catch (InterruptedException e) {e.printStackTrace();} finally {redisLock.unlock();renewal.stopRenewal(); // 停止续期}
} else {System.out.println("获取锁失败");
}

总结

  1. 互斥性SET NX PX 确保只有一个线程能获取锁。
  2. 自动续期:定期 PEXPIRE 延长锁的存活时间。
  3. 安全释放:Lua 脚本保证只有锁的持有者才能删除。

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

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

相关文章

论文笔记:Rethinking Graph Neural Networks for Anomaly Detection

目录 摘要 “右移”现象 beta分布及其小波 实验 《Rethinking Graph Neural Networks for Anomaly Detection》&#xff0c;这是一篇关于图&#xff08;graph&#xff09;上异常节点诊断的论文。 论文出处&#xff1a;ICML 2022 论文地址&#xff1a;Rethinking Graph Ne…

神经网络常见激活函数 6-RReLU函数

文章目录 RReLU函数导函数函数和导函数图像优缺点pytorch中的RReLU函数tensorflow 中的RReLU函数 RReLU 随机修正线性单元&#xff1a;Randomized Leaky ReLU 函数导函数 RReLU函数 R R e L U { x x ≥ 0 a x x < 0 \rm RReLU \left\{ \begin{array}{} x \quad x \ge 0…

Vue(6)

一.路由板块封装 &#xff08;1&#xff09;路由的封装抽离 目标&#xff1a;将路由板块抽离出来 好处&#xff1a;拆分板块&#xff0c;利于维护 // 路由的使用步骤 5 2 // 5个基础步骤 // 1. 下载 v3.6.5 // 2. 引入 // 3. 安装注册 Vue.use(Vue插件) // 4. 创建路由对象…

【python】matplotlib(animation)

文章目录 1、matplotlib.animation1.1、FuncAnimation1.2、修改 matplotlib 背景 2、matplotlib imageio2.1、折线图2.2、条形图2.3、散点图 3、参考 1、matplotlib.animation 1.1、FuncAnimation matplotlib.animation.FuncAnimation 是 Matplotlib 库中用于创建动画的一个…

【东莞常平】戴尔R710服务器不开机维修分享

1&#xff1a;2025-02-06一位老客户的朋友刚开工公司ERP服务器一台戴尔老服务器故障无法开机&#xff0c;于是经老客户介绍找到我们。 2&#xff1a;服务器型号是DELL PowerEdge R710 这个服务器至少也有15年以上的使用年限了。 3&#xff1a;客户反馈的故障问题为&#xff1a;…

Spring AI -使用Spring快速开发ChatGPT应用

前言 Spring在Java生态中一直占据大半江山。最近我发现Spring社区推出了一个Spring AI项目&#xff0c;目前该项目还属于Spring实验性项目&#xff0c;但是我们可以通过该项目&#xff0c;可以非常快速的开发出GPT对话应用。 本篇文章将会对SpringAI进行简单的介绍和使用&#…

经典排序算法复习----C语言

经典排序算法复习 分类 交换类 冒泡快排 分配类 计数排序基数排序 选择类 选择排序 堆排序 归并类 归并排序 插入类 直接插入排序 希尔排序 折半插入排序 冒泡排序 基于交换。每一轮找最大值放到数组尾部 //冒泡排序 void bubSort(int* arr,int size){bool sorte…

BFS解决拓扑排序(3题)

目录 拓扑排序 1.如何排序&#xff1f; 2.如何形成拓扑排序 3.如何建图 1.看数据稠密度 2. 根据算法流程灵活建图 1.课程表 2.课程表2 3.火星词典 拓扑排序 找到做事情的先后顺序&#xff0c;拓扑排序的结果可能不是唯一的 1.如何排序&#xff1f; 1.找出图中入度为…

kafka 3.5.0 raft协议安装

前言 最近做项目&#xff0c;需要使用kafka进行通信&#xff0c;且只能使用kafka&#xff0c;笔者没有测试集群&#xff0c;就自己搭建了kafka集群&#xff0c;实际上笔者在很早之前就搭建了&#xff0c;因为当时还是zookeeper&#xff08;简称ZK&#xff09;注册元数据&#…

Unity项目接入xLua的一种流程

1. 导入xlua 首先导入xlua&#xff0c;这个不用多说 2. 编写C#和Lua交互脚本 基础版本&#xff0c;即xlua自带的版本 using System.Collections; using System.Collections.Generic; using UnityEngine; using XLua; using System; using System.IO;[Serializable] public…

四次挥手详解

文章目录 一、四次挥手各状态FIN_WAIT_1CLOSE_WAITFIN_WAIT_2LAST_ACKTIME_WAITCLOSE 二、双方同时调用close()&#xff0c;FIN_WAIT_1状态后进入CLOSING状态CLOSING状态 三、TIME_WAIT状态详解(1) TIME_WAIT状态下的2MSL是什么MSL &#xff08;报文最大生存时间&#xff09;为…

【嵌入式 Linux 音视频+ AI 实战项目】瑞芯微 Rockchip 系列 RK3588-基于深度学习的人脸门禁+ IPC 智能安防监控系统

前言 本文主要介绍我最近开发的一个个人实战项目&#xff0c;“基于深度学习的人脸门禁 IPC 智能安防监控系统”&#xff0c;全程满帧流畅运行。这个项目我目前全网搜了一圈&#xff0c;还没发现有相关类型的开源项目。这个项目只要稍微改进下&#xff0c;就可以变成市面上目前…

java: framework from BLL、DAL、IDAL、MODEL、Factory using oracle

oracel 21c sql: -- 创建 School 表 CREATE TABLE School (SchoolId CHAR(5) NOT NULL,SchoolName NVARCHAR2(500) NOT NULL,SchoolTelNo VARCHAR2(8) NULL,PRIMARY KEY (SchoolId) );CREATE OR REPLACE PROCEDURE addschool(p_school_id IN CHAR,p_school_name IN NVARCHAR2,p…

解决错误:CondaHTTPError: HTTP 000 CONNECTION FAILED for url

解决错误&#xff1a;CondaHTTPError: HTTP 000 CONNECTION FAILED for url 查看channels:vim ~/.condarcshow_channel_urls: true channels:- http://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/- http://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/msys2/…

Apache APISIX 快速入门

文章目录 apisix 快速入门什么是apisix有了 NGINX 和 Kong&#xff0c;为什么还需要 Apache APISIX&#xff1f;软件架构基于 Nginx 开源版本&#xff0c;而 Nginx 并不支持动态配置&#xff0c;为什么 Apache APISIX 声称自己可以实现动态配置&#xff1f; 安装配置 APISIX配置…

2025嵌入式高频面试题解析

一、概述 到了年初&#xff0c;是求职者最活跃的时间。本文梳理了嵌入式高频面试题&#xff0c;帮助求职者更好地准备面试&#xff0c;同时也为技术爱好者提供深入学习嵌入式知识的参考。 二、C 语言基础 2.1 指针与数组 问题 1&#xff1a;指针和数组的区别是什么&#xf…

1.攻防世界 baby_web

题目描述这里有提示&#xff0c;初始页面 进入题目页面如下 很简洁的页面只有一行HELLO WORLD ctrlu查看了源码也没有信息 用burp suite抓包&#xff0c;并发送到重放器 根据提示&#xff08;初始页面&#xff09;修改访问index.php文件 index.php index.php 是一种常见的…

什么是三层交换技术?与二层有什么区别?

什么是三层交换技术&#xff1f;让你的网络飞起来&#xff01; 一. 什么是三层交换技术&#xff1f;二. 工作原理三. 优点四. 应用场景五. 总结 前言 点个免费的赞和关注&#xff0c;有错误的地方请指出&#xff0c;看个人主页有惊喜。 作者&#xff1a;神的孩子都在歌唱 大家好…

【机器学习】数据预处理之数据归一化

数据预处理之数据归一化 一、摘要二、数据归一化概念三、数据归一化实现方法3.1 最值归一化方法3.2 均值方差归一化方法 一、摘要 本文主要讲述了数据归一化&#xff08;Feature Scaling&#xff09;的重要性及其方法。首先通过肿瘤大小和发现时间的例子&#xff0c;说明了不同…

【AIGC】语言模型的发展历程:从统计方法到大规模预训练模型的演化

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: AIGC | ChatGPT 文章目录 &#x1f4af;前言&#x1f4af;语言模型的发展历程&#xff1a;从统计方法到大规模预训练模型的演化1 统计语言模型&#xff08;Statistical Language Model, SLM&#xff09;&#xff1a;统…