使用redis+lua脚本实现分布式锁

Android BLE扫描指南:解决设备发现问题 假设你正在开发一个MAUI应用,用于扫描并连接到BLE设备。你的代码在Windows上运行得很好,但在Android上却无法发现任何设备。尽管你已经在中声明了必要的权限,并且在运行时请求这些权限,扫描还是无法工作。 阅读详情

分布式锁的应用场景

当多个机器(多个进程)会对同一条数据进行修改时,并且要求这个修改是原子性的。这里有两个限定:

  • 多个进程之间的竞争,意味着JDK自带的锁失效;
  • 原子性修改,意味着数据是有状态的,修改前后有依赖。

分布式锁的实现条件:

  • 高性能(加、解锁时高性能)
  • 可以使用阻塞锁与非阻塞锁。
  • 不能出现死锁。
  • 可用性(不能出现节点 down 掉后加锁失败)。

Redis使用分布式锁

本文将先介绍Redis的实现方式,当然Redis实现分布式锁有多种方案,本文介绍一种基于lua脚本的实现方案。后面笔者会介绍分布式锁的其他实现(基于 DB 的唯一索引和基于 ZK 的临时有序节点)。

本方案中Redis的实现主要基于setnx 和给予一个超时时间(防止释放锁失败)。
多个尝试获取锁的客户端使用同一个key做为目标数据的唯一键,value为锁的期望超时时间点;
首先进行一次setnx命令,尝试获取锁,如果获取成功,则设置锁的最终超时时间(以防在当前进程获取锁后奔溃导致锁无法释放)

这里利用 Redis set key 时的一个 NX 参数可以保证在这个 key 不存在的情况下写入成功。并且再加上 EX 参数可以让该 key 在超时之后自动删除。

注意:此处使用Jedis的如下方法,该命令可以保证 NX EX 的原子性。

一定不要把两个命令(NX EX)分开执行,如果在 NX 之后程序出现问题就有可能产生死锁。

String set(String key, String value, String nxxx, String expx, long time);

非阻塞锁

public  boolean tryLock(String key, String request) {
    String result = this.jedis.set(LOCK_PREFIX + key, request, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, 10 * TIME);
    if (LOCK_MSG.equals(result)){
        return true ;
    }else {
        return false ;
    }
}

阻塞锁

同时也可以实现一个阻塞锁:

//一直阻塞
public void lock(String key, String request) throws InterruptedException {
    for (;;){
        String result = this.jedis.set(LOCK_PREFIX + key, request, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, 10 * TIME);
        if (LOCK_MSG.equals(result)){
            break ;
        }
 //防止一直消耗 CPU 	
        Thread.sleep(DEFAULT_SLEEP_TIME) ;
    }
}
 //自定义阻塞时间
 public boolean lock(String key, String request,int blockTime) throws InterruptedException {
    while (blockTime >= 0){
        String result = this.jedis.set(LOCK_PREFIX + key, request, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, 10 * TIME);
        if (LOCK_MSG.equals(result)){
            return true ;
        }
        blockTime -= DEFAULT_SLEEP_TIME ;
        Thread.sleep(DEFAULT_SLEEP_TIME) ;
    }
    return false ;
}

解锁

解锁也很简单,其实就是把这个 key 删掉就万事大吉了,比如使用 del key 命令。

但现实往往没有那么 easy。

如果进程 A 获取了锁设置了超时时间,但是由于执行周期较长导致到了超时时间之后锁就自动释放了。这时进程 B 获取了该锁执行很快就释放锁。这样就会出现进程 B 将进程 A 的锁释放了。

所以最好的方式是在每次解锁时都需要判断锁是否是自己的。

这时就需要结合加锁机制一起实现了。

加锁时需要传递一个参数,将该参数作为这个 key 的 value,这样每次解锁时判断 value 是否相等即可。

为了更好的健壮性,将该操作封装为一个lua脚本,这样即可保证其原子性

public  boolean unlock(String key,String request){
    //lua script
    String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
    Object result = null ;
    if (jedis instanceof Jedis){
        result = ((Jedis)this.jedis).eval(script, Collections.singletonList(LOCK_PREFIX + key), Collections.singletonList(request));
    }else if (jedis instanceof JedisCluster){
        result = ((JedisCluster)this.jedis).eval(script, Collections.singletonList(LOCK_PREFIX + key), Collections.singletonList(request));
    }else {
        //throw new RuntimeException("instance is error") ;
        return false ;
    }
    if (UNLOCK_MSG.equals(result)){
        return true ;
    }else {
        return false ;
    }
}

该方案的缺点

key 超时之后业务并没有执行完毕但却自动释放锁了
如运行在Redis的集群,当进程1对master节点写入了锁,此时master节点宕机。slave节点提升为master而刚刚写入master的锁还未同步,此时进程2也将能够获取锁成功。
Ros入门 (十)----激光雷达避障 简易实现 本篇文章通过订阅/scan话题获取障碍物的距离信息,达到避障目的,提供部分代码,仅供参考。 阅读详情

相关推荐

GR00TN1.7国内本地下载+模型下在+hugingface无法连接,本地模型下载

GR00TN1.7

alsj123456的博客 97

Redis 实现分布式锁+执行lua脚本

本篇主要一步步演进手写redis分布式锁的实现, 包括 setnx -> set -> 过期时间 -> 误删锁 -> uuid控制锁误删-> lua脚本控制删锁的原子性等等.. 其实目前还有问题, 包括锁续期问题以及redis 可重入锁的问题有机会在完善吧需要注意 redis 中如何使用 lua脚本的, 因为一些原子性操作就是需要lua脚本来控制 包括 redission 框架也是通过lua脚本实现的.

qq_34285557的博客 2542

CVAT自动标注避坑指南:从nuctl安装到YOLOv5模型部署的完整流程

本文详细介绍了在CVAT中部署YOLOv5自动标注功能的完整流程与避坑指南。重点解决了从nuctl工具安装、项目创建时因网络问题导致的镜像拉取失败,到最终模型函数部署与CVAT集成的关键步骤。针对国内网络环境,提供了实用的镜像替换方案,帮助用户顺利完成基于CPU的自动化标注环境搭建。

pytorch8learner的博客 229

使用 Redis 和 Lua 实现分布式锁

分布式锁是一种用于多台服务器上处理同一资源的并发访问的锁机制。它用于协调分布式系统中的各个节点,确保它们的操作不会相互干扰。Redis (Remote Dictionary Server)是一种使用 C 语言编写的,开源的 in-memory 数据库系统,支持多种数据结构类型,如字符串、哈希表、列表、集合等。由于其可高效地存储键值对,并且具有多种灵活的使用方式,因此经常被用作缓存、会话存储和消息队列等场景。

BXA 4711

单细胞分析进阶:sctransform标准化在Seurat中的实战解析

本文深入解析了sctransform标准化方法在Seurat单细胞分析中的实战应用。通过对比传统对数标准化,sctransform能更有效地建模并剔除技术噪音,提升数据质量。文章提供了从环境配置、数据准备、核心参数解析到完整流程整合的详细指南,并针对常见问题给出解决方案,帮助研究者获得更清晰的细胞分群和更可靠的差异表达结果。

weixin_29248313的博客 151

ADS笔记,新旧两组仿真数据进行绘图和列表对比

原理图器件参数的不同,怎么进行对比观看,操作如下。

彭辉荣的博客 3869

分布式锁2:基于redis实现分布式锁 setnx+lua脚本

redis中setnx+expire是非原子操作, 除了用LUA脚本保证实现原子操作, 其实可以直接使用redis自带的set方法直接实现.setnx+expire+del 命令实现redis的分布式锁;其中 setnx 不存在则新增;给锁设置一个过期时间,防止锁忘记了释放。来抢锁,如果抢到之后,再用。

健康平安的活着的专栏 2944

STM32硬件SPI驱动W5500以太网模块全流程(附避坑指南)

本文详细介绍了STM32硬件SPI驱动W5500以太网模块的全流程,包括硬件架构设计、SPI接口选型、官方驱动移植、网络协议栈配置与优化等关键步骤。通过实战案例和性能对比数据,帮助开发者快速实现稳定高效的网络连接,特别提供了常见问题排查指南和性能调优技巧。

weixin_29194693的博客 268

Redis分布式锁结合Lua脚本实现

通过 Lua 脚本,Redisson 能够确保分布式锁的一系列操作(获取锁、设置过期时间、释放锁)的原子性,这对于实现分布式锁等关键功能至关重要。Lua 脚本不仅可以确保操作的原子性,还能提高性能,因为它可以避免客户端和服务器之间的多次往返通信。

m0_67363888的博客 895

Power Switch与Tap Cell关系

tap cell可以选用一般类型的tap cell,无须secondary pg pin,因为此时switch cell的阱电位接到输入power net上了,switch cell可以正常上电,也可以给core内正常供电,tap cell的阱电位接switch cell输出的power,需要注意的是此时switch cell与core内其他cell的阱电位是不同的,所以为了避免drc问题,需要在switch上盖hard blockage或者keepout margin。2)自带阱偏置的switch。

m0_61544122的博客 2336

基于深度学习的树木种类识别

本文介绍了基于深度学习的树木种类识别技术。我们将通过深度学习模型和图像处理技术实现对树木的自动识别与分类。首先,我们将介绍深度学习的基本原理和相关算法。接着,我们将详细说明树木种类识别的数据准备、模型构建和训练过程。最后,我们将给出代码示例,帮助读者深入了解和实践该技术。

一键难忘的博客 2316

redis使用lua脚本来实现分布式锁

redis分布式锁

w的博客 640

DeepSeek Harness 工程实践与高级特性:从测试到安全的完整指南

AI Agent 能执行命令、读写文件、自主决策,能力越强风险越大——删文件、泄密钥、死循环、竞态条件随时可能发生。本文是 DeepSeek Harness 系列第三篇,深入剖析其工程实践与高级特性:从单元测试到真实 API 冒烟测试的分层策略,拒绝 Mock 依赖、坚持"验证世界而非自我报告";从正交结果、规范化契约到 Dispose 静止的防御式编程铁律;以及跨平台多层进程沙箱、文件系统版本守卫、fail-closed 审批机制、模型编写的工作流引擎与上下文压缩等高级能力。

program哲学 207

【Go】使用lua脚本实现redis分布式锁

分布式锁的要求 实现分布式锁之前要明确一下分布式锁的要求 互斥性,在任意时刻,只能有一个进程持有锁 防死锁,不能因为持有锁的客户端宕机而使其他进程无法获取到锁。 加锁和解锁的必须是同一个进程。 保证锁的续租。 redis分布式锁的优缺点 redis实现的分布式锁性能会比zookeeper、etcd等实现的要好,但因为单点故障或者主备异步复制的问题,可能会出现当master宕机crash会导致多个client同时持有分布式锁。(这里的方案会出现这些问题) 因为etcd的高可靠、强一致存储,可以避免故障时出

码农印象 1302

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

使用Lua脚本保证原子性的Redis分布式锁实现

通过将 Redis 与 Lua 脚本结合使用,我们能够构建一个更安全、更高效的分布式锁,实现锁操作的原子性与一致性。这种方案非常适用于高并发的分布式系统,能够有效防止因锁误删导致的数据不一致和业务逻辑混乱问题。

Takumilove的博客 1173

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

使用Redis+Lua脚本实现分布式锁

1.1加锁 // 1. 从redis中获取锁,set k1 v1 px 20000 nx String uuid = UUID.randomUUID().toString(); Boolean lock = this.redisTemplate.opsForValue().setIfAbsent("lock", uuid, 2, TimeUnit.SECONDS); 使用Lua释放锁 // 2. 释放锁 del String script = "if redis.call('get', KEYS[1])

Cure The World的博客 2494

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

RedisTemplate使用lua脚本实现Redis分布式锁

RedisTemplate使用lua脚本实现Redis分布式锁 package com.jslc.analysis.utils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.script.RedisScript; import

zybiao2的专栏 1844

redis使用lua脚本实现分布式锁

package com.paic.phucp.console.djss; import com.paic.phucp.common.utils.RedisUtil; import org.springframework.stereotype.Component; import redis.clients.jedis.JedisCluster; import java.util.Collections; /** * 第一个为key,我们使用key来当锁名 * 第二个为value,传的是uid,唯一随..

qq_35572013的博客 1807

redis哨兵模式使用lua脚本实现分布式锁

spring redis和redis包在设置key值的时候,都是先调用setnx设置值,成功就返回1,然后通过Expire设置超时时间,这样会出现一个问题假如setnx成功,但是expire的时候,失败了,那么该值就会一直存在,这样会造成大的问题,这个问题怎么解决呢?我们可以通过redis lua脚本,让设置值和设置超时时间在redis服务端一次执行,就不会造成前面描述的问题。下面是实现分布式锁的

Mr_Smile2014的博客 4762

redis在使用lua脚本以及实现redis分布式锁

目录背景介绍环境准备redis运行lua脚本访问次数限制java调用脚本操作redisLua+Redis 断点调试环境搭建 背景介绍 Redis在2.6推出了脚本功能,允许开发者使用Lua语言编写脚本传到Redis中执行。使用脚本的好处如下: 1.减少网络开销:本来5次网络请求的操作,可以用一个请求完成,原先5次请求的逻辑放在redis服务器上完成。使用脚本,减少了网络往返时延。 2.原子操作:R...

牧竹子 8636

使用Redis的LUA脚本实现分布式锁

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.script.DefaultRedisScript; import org.springframework.stereotype.Component; import j.

诸葛小猿 321

go 使用lua脚本实现redis分布式锁

分布式锁的要求 实现分布式锁之前要明确一下分布式锁的要求 互斥性,在任意时刻,只能有一个进程持有锁 防死锁,不能因为持有锁的客户端宕机而使其他进程无法获取到锁。 加锁和解锁的必须是同一个进程。 保证锁的续租。 redis分布式锁的优缺点 redis实现的分布式锁性能会比zookeeper、etcd等实现的要好,但因为单点故障或者主备异步复制的问题,可能会出现当master宕机crash会导致多个client同时持有分布式锁。(这里的方案会出现这些问题) 因为etcd的高可靠、强一致存储,可以

weixin_46040684的博客 1260

使用 Lua 脚本在 Redis 中实现一些复杂的原子操作:分布式锁、计数器以及排行榜

使用 Lua 脚本在 Redis 中可以实现一些复杂的原子操作,比如分布式锁、计数器以及排行榜等。

学亮编程手记 825

Redis学习笔记(三)使用Lua脚本实现分布式锁

Redis在2.6推出了脚本功能,允许开发者使用Lua语言编写脚本传到Redis中执行。 使用Lua脚本的好处如下: 1.减少网络开销:本来5次网络请求的操作,可以用一个请求完成,原先5次请求的逻辑放在redis服务器上完成。使用脚本,减少了网络往返时延。 2.原子操作:Redis会将整个脚本作为一个整体执行,中间不会被其他命令插入。 3.复用:客户端发送的脚本会永久存储在...

Tinywan 545

使用redis setnx命令结合lua脚本实现分布式锁功能

使用redis setnx命令结合lua脚本实现分布式锁功能 public Map<String, List<catalog2Vo>> getCatalogJsonFromDBWithRedisLock() { //抢占分布式锁 String uuid = UUID.randomUUID().toString();//设置锁的唯一id Boolean lockBoolean = redisTemplate.opsForValue().s

qq_37293674的博客 549

Redis分布式锁使用lua脚本,实现分布式锁,及封装(Spring_boot)

一、分布式锁 分布式锁,是一种思想,它的实现方式有很多。比如,我们将沙滩当做分布式锁的组件,那么它看起来应该是这样的: 加锁 在沙滩上踩一脚,留下自己的脚印,就对应了加锁操作。其他进程或者线程,看到沙滩上已经有脚印,证明锁已被别人持有,则等待。 解锁 把脚印从沙滩上抹去,就是解锁的过程。 锁超时 为了避免死锁,我们可以设置一阵风,在单位时间后刮起,将脚印自动抹去。 分布式锁的实现有很多,比如基于数据库、memcached、Redis、系统文件、zookeeper等。它们的核心的理念跟上面的过程大致相同。 二

xie_yu1的博客 873
上一篇: 使用MongoDB实现消息队列的异步消息功能
下一篇: 伸展树的特性及实现
不能说的秘密go
博客等级 码龄12年 562粉丝 191原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值