当前位置: 首页 > 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;}
}

http://www.lryc.cn/news/211620.html

相关文章:

  • vue源码分析(七)—— createComponent
  • vue实现图片分页
  • Baklib专注:企业数字内容体验与知识管理
  • C++ 标准库随机数:std::default_random_engine
  • Python requests之Cookie
  • 【嵌入式项目应用】__嵌入式中,映射表的应用例子!
  • react中的useState和useImmer的用法
  • Can‘t compile code “launch: program <program_path> does not exist “
  • Mac电脑上升级nodejs
  • 基于单片机的太阳跟踪系统的设计
  • V3Det大规模词汇视觉检测数据集与LaRS海上全景障碍物检测数据集
  • ubuntu(18.04) 安装 blast
  • 3.2每日一题(定积分求抽水做工问题)
  • c语言基础:L1-063 吃鱼还是吃肉
  • <if> 标签中使用了不正确的语法。在 XML 中,<if> 标签不需要使用 <![CDATA[ ... ]]> 将条件语句包装起来。 否则会报错
  • Ubuntu 诞生 19 年
  • JVM进阶(3)
  • Qt QWidget、QDialog、QMainWindow的区别
  • 软考 系统架构设计师系列知识点之设计模式(10)
  • 【python爬虫】设计自己的爬虫 1. request封装
  • 8.0 新特性 - innodb_ddl_threads
  • pgAdmin 4 v7.8 发布,PostgreSQL 开源图形化管理工具
  • Realrek 2.5G交换机 8+1万兆光RTL8373-VB-CG方案简介
  • Linux命令随笔
  • 最新版scene-builder安装
  • 直击电商商城内核!一站式解决方案
  • rabbitmq安装、基本使用
  • Amaon CloudFront助力出海业务访问优化
  • python实现ModBusRTU服务端
  • yum安装node,npm