当前位置: 首页 > news >正文

基于 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脚本&#xff1a; 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文件的路径&#xff1a; src\core\vdom\create-componen…...

vue实现图片分页

本小节学会使用v-show和click 、v-bind&#xff0c;v-bind可以简写为: <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"…...

Baklib专注:企业数字内容体验与知识管理

随着科技的发展&#xff0c;消费者对数字体验的依赖程度攀升&#xff0c;品牌正面临着越来越大的压力。数字化体验作为当下最热门的话题之一&#xff0c;无论是传统企业还是互联网企业&#xff0c;都在积极探索创新方案和具体措施&#xff0c;从而提高用户的数字化体验&#xf…...

C++ 标准库随机数:std::default_random_engine

库头文件 #include <random> // 通过种子值设置随机数生成器 std::default_random_engine rng(seed);// 不设置种子值&#xff0c;使用默认值 std::default_random_engine rng; // 生成一个0到9之间的随机整数 int random_int rng() % 10;// 生成一个0到1之间的随机浮…...

Python requests之Cookie

视频版教程&#xff1a;一天掌握python爬虫【基础篇】 涵盖 requests、beautifulsoup、selenium 在某些需要登录的网站或者或者应用&#xff0c;假如我们需要抓取登录后的内容&#xff0c;技术上本质通过session会话实现。服务器端存会话信息&#xff0c;浏览器通过Cookie携带…...

【嵌入式项目应用】__嵌入式中,映射表的应用例子!

目录 一、嵌入式中的映射表是什么&#xff1f; 二、映射表在串口数据解析中的应用 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. 更新基本类型数据 在函数式组件中&#xff0c…...

Can‘t compile code “launch: program <program_path> does not exist “

StackOverflow上有一个类似的提问 我的情况很特殊&#xff0c;上面的回答没有解决我的问题&#xff0c;最后我发现是我的cpp文件名称为数字开头&#xff08;类似于1_floy.cpp&#xff09;&#xff0c;把名字里的数字挪到后面就好了。。。。。...

Mac电脑上升级nodejs

第一步&#xff0c;先查看本机node.js版本&#xff1a; node -v 第二步&#xff0c;清除node.js的cache&#xff1a; sudo npm cache clean -f 第三步&#xff0c;安装 n 工具&#xff0c;这个工具是专门用来管理node.js版本的&#xff0c;别怀疑这个工具的名字&#xff0c…...

基于单片机的太阳跟踪系统的设计

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 技术交流认准下方 CSDN 官方提供的联系方式 文章目录 概要 一、设计的主要内容二、硬件电路设计2.1跟踪控制方案的选择2.1.1跟踪系统坐标系的选择2.2系统总体设计及相关硬件介绍…...

V3Det大规模词汇视觉检测数据集与LaRS海上全景障碍物检测数据集

V3Det与LaRS是ICCV2023上发表的数据集工作&#xff0c;规模都比较大&#xff0c;后续有可能会用到&#xff0c;因此记录下来。 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、解压&#xff0c;配置环境变量 tar zvxf ncbi-blast-2.14.1-x64-linux.tar.gz解压后改名为 blast 配置环境变量&#xff0c;可以不配置 使用的时候直接绝对路径使用 vim ~/.bashrc 将下面添加道最…...

3.2每日一题(定积分求抽水做工问题)

1、画图&#xff0c;把题目的容器画出来&#xff1a;球形容器&#xff0c;半径为R 2、根据容器的形状进行分析&#xff1a; 抽水的实质是不同深度的水抽出去走的位移是不一样的>抽水的过程 &#xff1a; &#xff08;1&#xff09;先考虑深度为 x到xdx 的薄层水抽出去做多少…...

c语言基础:L1-063 吃鱼还是吃肉

国家给出了 8 岁男宝宝的标准身高为 130 厘米、标准体重为 27 公斤&#xff1b;8 岁女宝宝的标准身高为 129 厘米、标准体重为 25 公斤。 现在你要根据小宝宝的身高体重&#xff0c;给出补充营养的建议。 输入格式&#xff1a; 输入在第一行给出一个不超过 10 的正整数 N&am…...

<if> 标签中使用了不正确的语法。在 XML 中,<if> 标签不需要使用 <![CDATA[ ... ]]> 将条件语句包装起来。 否则会报错

标签中使用了不正确的语法。在 XML 中&#xff0c; 标签不需要使用 <![CDATA[ ... ]]> 将条件语句包装起来。 否则会报错...

Ubuntu 诞生 19 年

导读2004 年 10 月 20 日&#xff0c;Ubuntu 4.10 正式发布&#xff0c;代号‘Warty Warthog’。 作为 Ubuntu 第一个版本&#xff0c;4.10 问世后立刻受到广大 Linux 用户欢迎。它搭载了当时最新的 GNOME 2.8 桌面环境&#xff0c;以及一系列实用软件&#xff0c;比如 Mozilla…...

JVM进阶(3)

一)什么是垃圾&#xff1f; 垃圾指的是在应用程序中没有任何指针指向的对象&#xff0c;这个对象就是需要被回收的垃圾&#xff0c;如果不及时的针对内存中的垃圾进行清理&#xff0c;那么这些垃圾对象所占用的内存空间可能一直保留到应用程序结束&#xff0c;被保留的空间无法…...

Qt QWidget、QDialog、QMainWindow的区别

QWidget QWidget是Qt框架中最基础的窗口类&#xff0c;可以理解为用户界面的最基本单元。QWidget类提供了一个空白窗口&#xff0c;可以通过继承该类来创建自定义的窗口类。QWidget类提供了基本的窗口属性和方法&#xff0c;如大小、位置、标题、图标等。 QDialog QDialog是…...

软考 系统架构设计师系列知识点之设计模式(10)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之设计模式&#xff08;9&#xff09; 所属章节&#xff1a; 老版&#xff08;第一版&#xff09;教材 第7章. 设计模式 第2节. 设计模式实例 相关试题 9. 某软件公司欲设计一款图像处理软件&#xff0c;帮助用户对拍…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

Spark 之 入门讲解详细版(1)

1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室&#xff08;Algorithms, Machines, and People Lab&#xff09;开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目&#xff0c;8个月后成为Apache顶级项目&#xff0c;速度之快足见过人之处&…...

Appium+python自动化(十六)- ADB命令

简介 Android 调试桥(adb)是多种用途的工具&#xff0c;该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具&#xff0c;其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利&#xff0c;如安装和调试…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入&#xff0c;一个是通过INMP441麦克风模块采集音频&#xff0c;一个是通过PCM5102A模块播放音频&#xff0c;那如果我们将两者结合起来&#xff0c;将麦克风采集到的音频通过PCM5102A播放&#xff0c;是不是就可以做一个扩音器了呢…...

C++ 基础特性深度解析

目录 引言 一、命名空间&#xff08;namespace&#xff09; C 中的命名空间​ 与 C 语言的对比​ 二、缺省参数​ C 中的缺省参数​ 与 C 语言的对比​ 三、引用&#xff08;reference&#xff09;​ C 中的引用​ 与 C 语言的对比​ 四、inline&#xff08;内联函数…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;和加载&#xff08;Load&#xff09;过程。提供了一个简洁直观的界面&#xff0c;以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/

使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题&#xff1a;docker pull 失败 网络不同&#xff0c;需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN&#xff0c;根据VPN原理&#xff0c;打通两个内网必然需要借助一个公共中继节点&#xff0c;ktconnect工具巧妙的利用k8s原生的portforward能力&#xff0c;简化了建立连接的过程&#xff0c;apiserver间接起到了中继节…...