Redis之Lua脚本

Redis之Lua脚本—

Redission不仅提供了一套丰富的Redis客户端功能,还增加了很多高级功能,其中就包括分布式锁、发布和订阅、支持Lua脚本。Redission在底层利用Redis的SETNX命令实现分布式锁,并且处理了锁的续期问题,使用起来非常方便。

然而,为什么在实际项目中,我们还需要使用Lua脚本呢?
这主要是因为Redisson的分布式锁机制在某些特定场景下可能无法满足需求。

1,复杂的原子操作:Redisson的分布式锁主要用于实现简单的原子操作,例如“获取锁,执行操作,释放锁”。但是,如果你需要执行更复杂的原子操作,例如“获取锁,执行操作1,执行操作2,释放锁”,这时就需要使用Lua脚本。
.
2,自定义的锁机制:在某些场景下,你可能需要自定义锁的机制,例如锁的公平性、锁的>时时间等。虽然Redisson提供了一些配置选项,但是如果你需要更细粒度的控制,那么使用Lua脚本可能是更好的选择。
.
3,跨多个Redis实例的操作:如果你需要跨多个Redis实例进行操作,例如在一个Redis实例上获取锁,在另一个Redis实例上执行操作,那么使用Lua脚本可能更方便,能够避免跨多个Redis实例操作时可能出现的竞态条件或数据不一致问题
.
4,避免网络开销:使用Lua脚本可以将多个操作合并为一个操作,从而减少网络开销。这在某些对性能要求较高的场景下非常有用。

Lua脚本介绍

Redis从2.6版本开始,通过内嵌一个Lua解释器,支持在服务器端执行Lua脚本。这个特性为Redis提供了非常大的灵活性。通过Lua脚本,我们可以实现复杂的逻辑,包括判断、循环等这在纯Redis命令中是很难实现的
.

Lua是一种轻量级的解释型脚本语言,直接在运行时执行Lua脚本,而无需预先编译。 Lua脚本的主要优点包括:
简单:Lua的语法简洁直观,易于学习。
高效:尽管Lua是解释型语言,但它的执行速度非常快,因为编译成字节码。
安全:Lua提供了沙盒环境,允许在隔离的环境中运行代码,从而提高安全性。
灵活:Lua可以很容易地与其他语言(如C、C++、Java等)集成,使得你可以在其他应用程序中嵌入Lua脚本,扩展应用程序的功能。

Lua脚本为啥是高性能的?

轻量级:Lua是一种轻量级脚本语言,解释器体积小、启动速度快,消耗的内存资源较少,使得Lua脚本在运行时具有较低的开销
.
动态类型:Lua是一种动态类型语言,它允许变量在运行时改变类型。这种灵活性避免了静态类型语言在类型转换和类型检查方面的开销,使得Lua脚本在执行时更加高效。
.
即时编译:Lua使用了一种混合的编译和解释策略,它将脚本代码编译成字节码,然后在运行时解释执行。这种即时编译的方式可以在一定程度上提高执行效率,因为编译后的字节码更加优化和紧凑。
.
垃圾回收:Lua内置了一个高效的垃圾回收机制,可以自动管理内存。这减少了开发人员手动管理内存的负担,避免了内存泄漏和内存碎片问题,使得Lua脚本在长时间运行时仍能保持稳定的性能。
.
协程支持:Lua内置了对协程(coroutine)的支持,这是一种轻量级的线程,可以在单个线程中并发执行多个任务。协程的使用可以减少线程切换和同步的开销,提高脚本的并发性能

接下来,自定义自旋锁、通过Lua脚本实现分布式锁操作


public class RedisLockHelper {private Logger logger = LoggerFactory.getLogger(RedisLockHelper.class);/*** 加锁超时时间:500毫秒*/private static final long TIME_OUT = 500L;//定义获取锁的lua脚本private final static DefaultRedisScript<Long> LOCK_LUA_SCRIPT = new DefaultRedisScript<>("if redis.call('SETNX', KEYS[1], ARGV[1]) == 1 then return redis.call('PEXPIRE', KEYS[1], ARGV[2]) else return 0 end", Long.class);//定义释放锁的lua脚本private final static DefaultRedisScript<Long> RELEASE_LOCK_LUA_SCRIPT = new DefaultRedisScript<>("if redis.call('GET',KEYS[1]) == ARGV[1] then return redis.call('DEL',KEYS[1]) else return -1 end", Long.class);@Lazy@Autowiredprivate RedisTemplate<String, String> redisTemplate;/*** 自旋锁* @param lockKey* @param lockValues* @param expire* @return*/private Boolean spinLock(String lockKey, String lockValues, int expire){long startTime = System.currentTimeMillis();while (true){boolean lockRes = tryLock(lockKey, lockValues, expire);if(lockRes){return Boolean.TRUE;}//加锁消耗时长long consumeTime = System.currentTimeMillis() - startTime;if(consumeTime >= TIME_OUT){logger.warn("获取锁超时:锁key值:{}", lockKey);return Boolean.FALSE;}try {Thread.sleep(50);} catch (InterruptedException e) {e.printStackTrace();}}}public boolean tryLock(String lockKey, String value, int expire) {// 参数一:redisScript,参数二:key列表Long result = redisTemplate.execute(LOCK_LUA_SCRIPT, Collections.singletonList(lockKey), value, String.valueOf(expire));if(result != null && result == 1L){if(logger.isDebugEnabled()){logger.info("[加锁成功]result:{}, key:[{}], value:[{}] ", result, lockKey, value);}return true;}else {logger.warn("[加锁失败]result:{}, key:[{}], value:[{}] ", result, lockKey, value);return false;}}public void releaseLock(String lockKey, String value) {Long result = redisTemplate.execute(RELEASE_LOCK_LUA_SCRIPT, Collections.singletonList(lockKey), value);if(result != null && result == 1L){if(logger.isDebugEnabled()){logger.info("[锁释放环节]:锁释放成功!result:{}, key:[{}], value:[{}] ", result, lockKey, value);}}else {logger.warn("[锁释放环节]:查询不到锁!result:{}, key:[{}], value:[{}] ", result, lockKey, value);}}public static String getLockValues() {return UUID.randomUUID().toString().replace("-", "");}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/86388.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【QandA C++】面向过程、面向对象、多态的原理、虚函数表、虚表指针、虚析构、虚构造、虚函数、纯虚函数等重点知识汇总

目录 面向过程和面向对象 面向对象的三大特性 多态的条件和原理 虚表存放位置、虚表指针初始化时间 析构函数为什么要为虚函数 构造函数为什么不能为虚函数 虚函数和纯虚函数的实现原理 虚函数和纯虚函数的区别 面向过程和面向对象 面向过程的&#xff0c;关注的是过程…

Kubernetes的容器批量调度引擎 Volcano

一个用于高性能工作负载场景下基于Kubernetes的容器批量调度引擎 Volcano是在Kubernetes上运行高性能工作负载的容器批量计算引擎。 它提供了Kubernetes目前缺少的一套机制&#xff0c;这些机制通常是许多高性能 工作负载所必需的&#xff0c;包括&#xff1a; - 机器学习/深度…

flurl监听报错返回的信息

前言 开发过程中使用flurl.http发送http请求&#xff0c;但是服务器有时候会返回400、404这样的错误&#xff0c;有时候会携带信息&#xff0c;比如json提示或者xml或者html的提示&#xff0c;一开始不知道怎么捕捉&#xff0c;需要结合apipost调试&#xff0c;经过百度查找&a…

关于遍历,递归,Divide and Conque,回溯,Memorization和DP的一个小结

个人的一个小结&#xff0c;参考了一些网上的思路&#xff1a; 遍历和Divide and Conquer分别代表至上而下和至下而上的两种处理问题的思路 遍历: 至上而下&#xff0c;对应回溯算法。函数签名一般是没有返回值的&#xff0c;例如void backtrack(…) Divide and Conquer: 至下…

三.vue2路由知识全总结

Vue Devtools&#xff1a;插件安装&#xff0c;展示模块中的数据 vue-router 应用场景&#xff1a;Vue Router 是 Vue.js 的官方路由。它与 Vue.js 核心深度集成&#xff0c;让用 Vue.js 构建单页应用变得轻而易举。 嵌套的路由/视图表模块化的、基于组件的路由配置路由参数、…

一拖三快充线(USB-C转三充)的解决方案--LDR6020P

DR6020P 是带有 3 组 6 路 DRP USB-C 及 PD 通信协议处理模块和 USB2.0 Device 功能的 16 位 RISC MCU&#xff0c;内置 8K16 位 MTP 程序存储器&#xff08;可烧录 1000 次&#xff09;&#xff0c;512 字节的数据存储器&#xff08;SRAM&#xff09;。内置 LDO 5V 输出&#…

通讯网关软件011——利用CommGate X2ODBC实现DDE数据转入ODBC

本文介绍利用CommGate X2ODBC实将DDE数据源中的数据转入到ODBC数据源。CommGate X2ODBC是宁波科安网信开发的网关软件&#xff0c;软件可以登录到网信智汇(http://wangxinzhihui.com)下载。 【案例】如下图所示&#xff0c;将DDE数据源&#xff08;如Excel&#xff09;的数据写…

postgresql-触发器

postgresql-触发器 触发器概述创建触发器管理触发器删除触发器事件触发器创建事件触发器修改触发器删除事件触发器 触发器概述 PostgreSQL 触发器&#xff08;trigger&#xff09;是一种特殊的函数&#xff0c;当某个数据变更事件&#xff08;INSERT、UPDATE、 DELETE 或者 TR…

uniapp获取openid

要获取用户的openid&#xff0c;需要使用微信小程序的登录API。以下是一个简单的示例代码&#xff1a; // 在page中引入wx-login组件 import wxLogin from /components/wx-loginexport default {components: { wxLogin },data() {return {openid: }},methods: {// wxLogin组件…

【3dmax】怎么将点删除而面保留

在编辑多边形模式下&#xff0c;选择点模式&#xff0c;选择要删除的点&#xff0c;在下拉面板中找到【移除】

Mysql——压缩包方式安装教程

一.Mysql压缩包下载方式 zip版&#xff08;5.7及8.0&#xff09;的下载需到官方网站下载&#xff0c;不同版本对应能安装在不同的操作系统下&#xff0c;本次介绍的是mysql-8.0.30-winx64在win10下的安装方式。 下载网址&#xff1a;MySQL :: Download MySQL Community Server …

【Nuxt3】路由参数(动态路由、嵌套路由)

页面路由参数 query 参数 目录 |- pages | |- foo.vue路由地址 https://loaclhost:8080/foo?id1参数获取 // foo.vue <template><div>id: {{ route.query.id }}</div> </template><script setup lang"ts"> const route useRoute() …

描述符——配置描述符

描述符定义 描述符实现 /*** brief USB configuration descriptor.*/ typedef struct __attribute__ ((packed)) {uint8_t bLength ; /**< Size of this descriptor in bytes. */uint8_t bDescriptorType ; /**< CONFIGURATION Descriptor Type. */ui…

基于同名面片的TLS测站点云配准

1、原理介绍 2、代码介绍 基于C++编写的程序代码如下,其依赖eigen矩阵运算库,在创建工程时包含库目录中使用了相对路径,因此其下载下来直接可以运行,不用单独在设置环境,非常方便。

<图像处理> Shi-Tomasi角点检测

Shi-Tomasi角点检测 参考Harris角点检测方法&#xff0c;它是通过下式来判断是否为角点的&#xff1a; R d e t ( C ( x , y ) ) − k ( t r a c e ( C ( x , y ) ) ) 2 Rdet(C(x,y))-k(trace(C(x,y)))^2 Rdet(C(x,y))−k(trace(C(x,y)))2 式中&#xff0c;C(x,y)为自相关矩…

云原生微服务治理:服务发现、负载均衡与熔断策略

文章目录 什么是云原生微服务治理&#xff1f;服务发现客户端发现服务器端发现 负载均衡Ribbon - 基于客户端的负载均衡Nginx - 基于服务器的负载均衡 熔断策略Hystrix - 熔断器模式 结论 &#x1f389;欢迎来到云计算技术应用专栏~云原生微服务治理&#xff1a;服务发现、负载…

Spring Cloud Gateway快速入门(二)——断言工厂

文章目录 前言1. 什么是Gateway断言工厂2. 为什么要使用断言2.1. 调试和开发&#xff1a;2.2. 防御性编程&#xff1a;2.3. 文档和可读性&#xff1a;2.4. 测试&#xff1a; 3. 常用的Gateway断言工厂3.1 Path断言工厂3.2 Method断言工厂3.3 Header断言工厂3.4 时间断言工厂 4.…

北邮22级信通院数电:Verilog-FPGA(1)实验一“跑通第一个例程” 过程中遇到的常见问题与解决方案汇总(持续更新中)

北邮22信通一枚~ 跟随课程进度更新北邮信通院数字系统设计的笔记、代码和文章 持续关注作者 迎接数电实验学习~ 获取更多文章&#xff0c;请访问专栏&#xff1a; 北邮22级信通院数电实验_青山如墨雨如画的博客-CSDN博客 目录 问题一&#xff1a;Verilog代码没有跑通 报…

LabVIEW使用ModbusTCP协议构建分布式测量系统

LabVIEW使用ModbusTCP协议构建分布式测量系统 分布式测量系统主要用于监控远程物体。这种系统允许对系统用户获得的数据进行全面的数据收集、处理、存储和组织访问。它们可能包括许多不同类型的传感器。 在任何具有互联网接入的个人计算机上运行的软件都会发送来自传感器的测…

【kubernetes】k8s各组件运行流程以及高可用

1 Master节点的组件 Master节点包含三个组件和存储组件(Master的组件不一定要跟存储组件部署在同一台机器)&#xff1a; apiserver&#xff1a;提供RESTful风格的操作的API&#xff0c;其它组件之间通过API进行交互scheduler&#xff1a;调度器&#xff0c;负责决策将Pod安排…