首页 > 数据库 >redis使用setnx+lua实现分布式锁

redis使用setnx+lua实现分布式锁

时间:2023-04-03 12:55:05浏览次数:55  
标签:释放 lua redis value Lua key setnx redisTemplate 分布式

在Redis中,使用SETEX命令(对应RedisTemplate的setIfAbsent方法)可以实现一个最简易的分布锁。SETEX命令当key不存在的话,才会设置key的值,如果可以已经存在,就不做任何操作。

为了避免锁无法被释放,就给这个key(也就是锁)设置一个过期时间。

为了保证解锁操作的原子性,使用Lua脚本进行释放锁操作

为了防止误删其他的锁,在Lua脚本中通过key对应的value(唯一值)来判断是否要释放锁

最简单的分布式锁实现

不使用Lua脚本

// key 的唯一性可以关联业务
String key = "lockKey";
//value 的唯一性通过UUID生成
String value = UUID.randomUUID().toString().replaceAll("-", "");
//添加分布式锁,过期时间30秒
        Boolean absent = redisTemplate.opsForValue().setIfAbsent(key, value, 300000, TimeUnit.MILLISECONDS);
logger.info("执行相关的业务逻辑操作");
//释放锁
redisTemplate.delete(key);


添加Lua脚本保证原子性

1.新建Lua脚本

释放锁时,先比较锁对应的 value 值是否相等,避免锁的误释放。

if redis.call("get",KEYS[1]) == ARGV[1] then
    return redis.call("del",KEYS[1])
else
    return 0
end

2.使用Lua脚本释放锁

logger.info("执行相关的业务逻辑操作");
//redisTemplate.delete(key);
DefaultRedisScript<Long> script = new DefaultRedisScript<Long>();
script.setResultType(Long.class);
script.setScriptSource(new ResourceScriptSource(new ClassPathResource("lock.lua")));
String lockValue = (String) redisTemplate.opsForValue().get(key);
if(lockValue != null && value.equals(lockValue)) {
    List<String> keys = new ArrayList<>();
    keys.add(key);
    //执行脚本
    Long execute = (Long)redisTemplate.execute(script, keys, value);
    logger.info("execute=" + execute);
    logger.info("释放分布锁,key=" + key);
}

参考资料

标签:释放,lua,redis,value,Lua,key,setnx,redisTemplate,分布式
From: https://www.cnblogs.com/1963942081zzx/p/17282758.html

相关文章

  • Redis6 集群单机安装
    Redis6集群单机安装官网下载https://download.redis.io/releases/redis-6.2.6.tar.gzhttp://download.redis.io/redis-stable.tar.gz文档参考https://redis.io/documentation解压编译#安装编译需要的tclyum-yinstallgcctclrm-rf/data/redismkdir-p/data/re......
  • Redis下载与安装
    在Linux系统安装Redis步骤:1、将Redis安装包上传到Linux2、解压安装包,命令:tar-zxvfredis-4.0.0.tar.gz-C/usr/local3、安装Redis的依赖环境gcc,命令:yuminstallgcc-c++4、进入/usr/local/redis-4.0.0,进行编译,命令:make5、进入redis的src目录,进行安装,命令:makeinstall 在......
  • 决战圣地玛丽乔亚Day46----Redis哨兵模式
    哨兵模式Sentinel:  自动感知Master故障并选择一个Slave切换为Master,实现故障的自动转移能力。1.监控:持续监控主从是否健康,是否处于预期的工作状态.2.主从的动态切换:当Master故障后,哨兵启动自动故障恢复:从slave中选一个新的master3.通知机制:竞选出来新的master后,通知客户......
  • Docker - 安装Redis
    目录前言环境安装Redis下载Redis安装Redis配置Redis前言记录下Docker下Redis的安装环境Centos7+Docker23.0.1+Redis6.2.7安装Redis下载Redis指定版本下载redis,版本可通过仓库https://hub.docker.com查看dockerpullredis:6.2.7安装Redis创建redis配置......
  • Day 21 21.1 数据库之redis
    Redisredis介绍定义Redis(RemoteDictionaryServer,远程字典服务)是一个使用ANSIC编写的开源、支持网络、基于内存、可选持久性的键值对存储数据库,是NoSQL数据库。redis的出现主要是为了替代早期的Memcache缓存系统的。map内存型(数据存放在内存中)的非关系型(nosql)key-......
  • Day 21 21.2 数据库之Python操作redis
    Python操作redis(1)连接redis#方式1importredisr=redis.Redis(host='127.0.0.1',port=6379)r.set('foo','Bar')print(r.get('foo'))#方式2importredispool=redis.ConnectionPool(host='127.0.0.1',port=63......
  • redis高可用
    一、关系数据库与非关系型数据库1.1关系型数据库1.关系型数据库是一个结构化的数据库,创建在关系模型(二维表格模型)基础上,一般面向于记录2.SQL语句(标准数据查询语言)就是一种基于关系型数据库的语言,用于执行对关系型数据库中数据的检索和操作3.主流的关系型数据库包括Oracle、MySQ......
  • K8S用yaml资源清单部署redis数据库,数据持久化保存
    1.创建redis存储数据目录和配置文件mkdir-p/data/redis/redis-config/touch/data/redis/redis-config/redis.confcat>>/data/redis/redis-config/redis.conf<<EOFrequirepass123456bind0.0.0.0save9001save30010save6010000EOF2.编写redis的yaml资源清单api......
  • Redis面试题
    NoSQL是什么?NoSQL(NotOnlySQL的缩写)泛指非关系型的数据库,主要针对的是键值、文档以及图形类型数据存储。并且,NoSQL数据库天生支持分布式,数据冗余和数据分片等特性,旨在提供可扩展的高可用高性能数据存储解决方案。一个常见的误解是NoSQL数据库或非关系型数据库不能很好地存......
  • 热更新—内嵌Lua
    一、Lua简介    C++是一种编译型语言,执行效率高,但每次对程序修改都需要重新编译,当项目较大时,编译起来比较费时。    Lua是一种用C语言编写的脚本语言,源码开源,具有体积小,效率高的特点,可嵌入到应用程序中对应用程序进行拓展。因此可将其和C++程序结合起来,既保留了C++程序......