基于 Redis + Lua 脚本实现分布式锁,确保操作的原子性
1.加锁的Lua脚本: lock.lua
--- -1 failed
--- 1 success--- getLock key
local result = redis.call('setnx' , KEYS[1] , ARGV[1])
if result == 1 then--PEXPIRE:以毫秒的形式指定过期时间redis.call('pexpire' , KEYS[1] , 3600000)
elseresult = -1;-- 如果value相同,则认为是同一个线程的请求,则认为重入锁local value = redis.call('get' , KEYS[1])if (value == ARGV[1]) thenresult = 1;redis.call('pexpire' , KEYS[1] , 3600000)end
end
-- 如果获取锁成功,则返回 1
return result
2.解锁的Lua脚本: unLock.lua
if redis.call('get', KEYS[1]) == ARGV[1]thenreturn redis.call('del', KEYS[1])elsereturn 0
end
3.将资源文件放在资源文件夹下

4.Java中调用lua脚本
1)获取文件方式
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.scripting.support.ResourceScriptSource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.Arrays;/*** @Author: best_liu* @Description:* @Date Create in 14:04 2023/10/26* @Modified By:*/
@Slf4j
@RestController
public class LuaLock {@Autowiredprivate RedisTemplate redisTemplate;@GetMapping(value = "/getLock")public Long getLock() {DefaultRedisScript<Long> script = new DefaultRedisScript<Long>();script.setResultType(Long.class);
// 获取lua文件方式script.setScriptSource(new ResourceScriptSource(new ClassPathResource("script/lock.lua")));Long execute = (Long) redisTemplate.execute(script, Arrays.asList("best_liu"),"best_liu20231026150600");return execute;}
}
2)lua字符串方式
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.Arrays;/*** @Author: best_liu* @Description:* @Date Create in 14:04 2023/10/26* @Modified By:*/
@Slf4j
@RestController
public class LuaLock {@Autowiredprivate RedisTemplate redisTemplate;@GetMapping(value = "/getLock")public Long getLock() {DefaultRedisScript<Long> script = new DefaultRedisScript<Long>();script.setResultType(Long.class);
// 获取lua文件方式
// script.setScriptSource(new ResourceScriptSource(new ClassPathResource("script/lock.lua")));String lua = "local result = redis.call('setnx' , KEYS[1] , ARGV[1])\n" +"if result == 1 then\n" +" redis.call('pexpire' , KEYS[1] , 3600000)\n" +"else\n" +" result = -1;\n" +" local value = redis.call('get' , KEYS[1])\n" +" if (value == ARGV[1]) then\n" +" result = 1;\n" +" redis.call('pexpire' , KEYS[1] , 3600000)\n" +" end\n" +"end\n" +"return result";script.setScriptText(lua);Long execute = (Long) redisTemplate.execute(script, Arrays.asList("best_liu"),"best_liu20231026150600");return execute;}
}
5.jedis调用Lua脚本实现分布式重试锁
1)引入jedis依赖
<!-- jedis --><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>2.9.0</version></dependency>
2)jedis调用lua
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import redis.clients.jedis.Jedis;import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;@Slf4j
@RestController
public class LuaLock {@GetMapping(value = "/getLock")public Long getLock() {//获取连接Jedis jedis = new Jedis("127.0.0.1", 6379);String lua = "local result = redis.call('setnx' , KEYS[1] , ARGV[1])\n" +"if result == 1 then\n" +" redis.call('pexpire' , KEYS[1] , ARGV[2])\n" +"else\n" +" result = -1;\n" +" local value = redis.call('get' , KEYS[1])\n" +" if (value == ARGV[1]) then\n" +" result = 1;\n" +" redis.call('pexpire' , KEYS[1] , ARGV[2])\n" +" end\n" +"end\n" +"return result";List<String> keys = new ArrayList<>();List<String> values = new ArrayList<>();keys.add("best_liu");values.add("best_liu20231026150600");values.add("3600000");Object result = jedis.eval(lua, keys, values);System.out.println(result);return 1L;}
}
相关文章:
基于 Redis + Lua 脚本实现分布式锁,确保操作的原子性
1.加锁的Lua脚本: lock.lua --- -1 failed --- 1 success--- getLock key local result redis.call(setnx , KEYS[1] , ARGV[1]) if result 1 then--PEXPIRE:以毫秒的形式指定过期时间redis.call(pexpire , KEYS[1] , 3600000) elseresult -1;-- 如果value相同&…...
vue源码分析(七)—— createComponent
文章目录 前言一、createComponent 参数说明二、createComponent 源码详解1.baseCtor的实际指向2.extend 方法3.判断Ctor是否是函数的判断4.installComponentHooks方法5.返回一个带标识的组件 vnode 前言 createComponent文件的路径: src\core\vdom\create-componen…...
vue实现图片分页
本小节学会使用v-show和click 、v-bind,v-bind可以简写为: <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"…...
Baklib专注:企业数字内容体验与知识管理
随着科技的发展,消费者对数字体验的依赖程度攀升,品牌正面临着越来越大的压力。数字化体验作为当下最热门的话题之一,无论是传统企业还是互联网企业,都在积极探索创新方案和具体措施,从而提高用户的数字化体验…...
C++ 标准库随机数:std::default_random_engine
库头文件 #include <random> // 通过种子值设置随机数生成器 std::default_random_engine rng(seed);// 不设置种子值,使用默认值 std::default_random_engine rng; // 生成一个0到9之间的随机整数 int random_int rng() % 10;// 生成一个0到1之间的随机浮…...
Python requests之Cookie
视频版教程:一天掌握python爬虫【基础篇】 涵盖 requests、beautifulsoup、selenium 在某些需要登录的网站或者或者应用,假如我们需要抓取登录后的内容,技术上本质通过session会话实现。服务器端存会话信息,浏览器通过Cookie携带…...
【嵌入式项目应用】__嵌入式中,映射表的应用例子!
目录 一、嵌入式中的映射表是什么? 二、映射表在串口数据解析中的应用 1. 数据结构 2. 指令、函数映射表 3. 串口解析函数实现 三、映射表在UI设计中的应用 1. 数据结构 2. 函数映射表 3. 定义两个变量保存当前场景和上一个场景 4. 按下Up按键 跳转到指定场…...
react中的useState和useImmer的用法
文章目录 一、useState1. 更新基本类型数据2. 更新对象3. 更新嵌套对象4. 更新数组5.更新数组对象 二、Immer1. 什么是Immer2. 使用use-immer更新嵌套对象3. 使用useImmer更新数组内部的对象 一、useState react中文官网教程 1. 更新基本类型数据 在函数式组件中,…...
Can‘t compile code “launch: program <program_path> does not exist “
StackOverflow上有一个类似的提问 我的情况很特殊,上面的回答没有解决我的问题,最后我发现是我的cpp文件名称为数字开头(类似于1_floy.cpp),把名字里的数字挪到后面就好了。。。。。...
Mac电脑上升级nodejs
第一步,先查看本机node.js版本: node -v 第二步,清除node.js的cache: sudo npm cache clean -f 第三步,安装 n 工具,这个工具是专门用来管理node.js版本的,别怀疑这个工具的名字,…...
基于单片机的太阳跟踪系统的设计
欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 技术交流认准下方 CSDN 官方提供的联系方式 文章目录 概要 一、设计的主要内容二、硬件电路设计2.1跟踪控制方案的选择2.1.1跟踪系统坐标系的选择2.2系统总体设计及相关硬件介绍…...
V3Det大规模词汇视觉检测数据集与LaRS海上全景障碍物检测数据集
V3Det与LaRS是ICCV2023上发表的数据集工作,规模都比较大,后续有可能会用到,因此记录下来。 V3Det: Vast Vocabulary Visual Detection Dataset Paper: https://arxiv.org/abs/2304.03752 URL: https://v3det.openxlab.org.cn/ 在现实世界中…...
ubuntu(18.04) 安装 blast
1、下载 https://ftp.ncbi.nlm.nih.gov/blast/executables/blast/LATEST/2、解压,配置环境变量 tar zvxf ncbi-blast-2.14.1-x64-linux.tar.gz解压后改名为 blast 配置环境变量,可以不配置 使用的时候直接绝对路径使用 vim ~/.bashrc 将下面添加道最…...
3.2每日一题(定积分求抽水做工问题)
1、画图,把题目的容器画出来:球形容器,半径为R 2、根据容器的形状进行分析: 抽水的实质是不同深度的水抽出去走的位移是不一样的>抽水的过程 : (1)先考虑深度为 x到xdx 的薄层水抽出去做多少…...
c语言基础:L1-063 吃鱼还是吃肉
国家给出了 8 岁男宝宝的标准身高为 130 厘米、标准体重为 27 公斤;8 岁女宝宝的标准身高为 129 厘米、标准体重为 25 公斤。 现在你要根据小宝宝的身高体重,给出补充营养的建议。 输入格式: 输入在第一行给出一个不超过 10 的正整数 N&am…...
<if> 标签中使用了不正确的语法。在 XML 中,<if> 标签不需要使用 <![CDATA[ ... ]]> 将条件语句包装起来。 否则会报错
标签中使用了不正确的语法。在 XML 中, 标签不需要使用 <![CDATA[ ... ]]> 将条件语句包装起来。 否则会报错...
Ubuntu 诞生 19 年
导读2004 年 10 月 20 日,Ubuntu 4.10 正式发布,代号‘Warty Warthog’。 作为 Ubuntu 第一个版本,4.10 问世后立刻受到广大 Linux 用户欢迎。它搭载了当时最新的 GNOME 2.8 桌面环境,以及一系列实用软件,比如 Mozilla…...
JVM进阶(3)
一)什么是垃圾? 垃圾指的是在应用程序中没有任何指针指向的对象,这个对象就是需要被回收的垃圾,如果不及时的针对内存中的垃圾进行清理,那么这些垃圾对象所占用的内存空间可能一直保留到应用程序结束,被保留的空间无法…...
Qt QWidget、QDialog、QMainWindow的区别
QWidget QWidget是Qt框架中最基础的窗口类,可以理解为用户界面的最基本单元。QWidget类提供了一个空白窗口,可以通过继承该类来创建自定义的窗口类。QWidget类提供了基本的窗口属性和方法,如大小、位置、标题、图标等。 QDialog QDialog是…...
软考 系统架构设计师系列知识点之设计模式(10)
接前一篇文章:软考 系统架构设计师系列知识点之设计模式(9) 所属章节: 老版(第一版)教材 第7章. 设计模式 第2节. 设计模式实例 相关试题 9. 某软件公司欲设计一款图像处理软件,帮助用户对拍…...
idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...
有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...
学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...
