【Redis深度专题】「核心技术提升」高级特性之Lua脚本执行机制的实现与探究

news2024/11/26 18:50:51

高级特性之Lua脚本执行机制的实现与探究

  • 内容梗概
  • 什么是Lua
    • Lua的应用
    • Lua的特点
    • Redis引入Lua脚本
      • Redis中引入Lua的原因
        • Lua脚本的原子处理能力
        • Lua减少网络开销
        • Lua脚本复用与提高效率
    • Redis中Lua的常用命令
      • 指令:EVAL
        • 指令格式
        • 案例介绍
        • Redis函数:call和pcall
          • redis.call操作
          • redis.pcall
    • redis-cli执行
      • 无参数执行
        • 多值传送示例
        • Linux命令执行
  • 最终总结

内容梗概

本文深入剖析Redis服务器初始化Lua环境的完整过程,重点解读Redis对Lua环境的核心优化。这些优化不仅重塑了Lua脚本的执行逻辑,还为Redis中的Lua脚本运行设定了特定的规则和限制。深度剖析伪客户端,洞察Redis命令在Lua环境中的执行细节;而脚本字典的解析则揭示了SCRIPT EXISTS命令的运作机制及脚本复制的实现原理。

此外,本文还详细解读EVAL和EVALSHA命令的内在逻辑,以及SCRIPT FLUSH、EXISTS、LOAD和KILL等关键脚本管理命令的实现机制。这些深入的分析与解读,对于深入理解Redis的Lua脚本功能,以及高效利用Redis的脚本管理能力具有重要意义。

什么是Lua

对于熟悉Redis功能的开发相关人员而言,Lua语言想必不会陌生。作为Redis的一个重要扩展,Lua在Redis中扮演着至关重要的角色,使得Redis具备了更为强大的脚本处理能力。

Lua是一款轻量级脚本语言,以标准C语言为基础,其源码开放,设计初衷即是为了嵌入各类应用程序,赋予它们灵活的扩展与定制能力。Lua的诞生可追溯到1993年,由巴西里约热内卢天主教大学的研究小组精心打造,团队成员包括Roberto Ierusalimschy、Waldemar Celes以及Luiz Henrique de Figueiredo等杰出学者

Lua的应用

Lua凭借其灵活、轻量、易嵌入的特点,在游戏开发、独立应用脚本、Web应用脚本、数据库和插件扩展等多个领域都有着广泛的应用。
在这里插入图片描述

  • 应用程序的灵活扩展与个性化定制:作为一种轻量级的脚本语言,Lua能够迅速集成到多种应用中,为应用程序的动态逻辑扩展提供强大支持,满足用户多样化的功能需求,实现真正的个性化定制。

  • 游戏开发中的高效更新与维护:游戏开发者可以利用Lua编写游戏的核心逻辑、角色行为以及事件触发机制,极大地提升了游戏的交互性和可玩性。更值得一提的是,当游戏需要更新或维护时,开发者仅需对Lua脚本进行修改,无需重新安装整个游戏,这极大地提高了游戏的更新效率和可维护性。

  • 独立应用脚本的自动化与智能化:通过Lua脚本,开发者可以轻松实现应用的自动化操作、数据处理以及界面交互,极大地提升了应用的易用性和智能化水平。

  • Web应用脚本的高效处理与交互:作为服务器端脚本语言,Lua能够高效处理Web请求、生成动态页面以及实现复杂的业务逻辑。同时,Lua还能与Web前端技术无缝对接,实现前后端数据的实时交互和处理,为Web应用带来更加流畅和高效的用户体验。

  • 数据库与插件开发的强大扩展:通过编写Lua脚本,开发者可以实现对数据库的灵活操作、自定义查询以及数据转换等功能。同时,Lua还可以作为插件开发语言,为各种应用提供丰富的功能和特性,进一步拓展应用的使用场景和可能性。

Lua的特点

Lua凭借诸多独特优势,如简洁的语法、高效的字节码执行、复杂数据结构处理能力、动态类型特性以及自动化的内存管理,成为嵌入式设备和智能移动设备中理想的脚本引擎。总体总结为一下六点,如下图所示。
在这里插入图片描述

  • 高效稳定】:Lua作为脚本语言,其高效性广受赞誉。众多大型程序选择用Lua编写易变部分,不仅未降低系统运行效率,反而显著提升了程序的稳定性和可扩展性。

  • 跨平台性】:Lua官方网站提供多平台发布包,如Linux/Unix、Windows等,轻松实现跨平台应用。

  • 方便嵌入】:Lua被明确定位为嵌入式脚本语言,与其他编程语言如C/C++交互流畅,也可嵌入Java和C#中,实现代码直接交互。

  • 简洁强大】:Lua作为过程化脚本语言,通过meta-mechanisms机制,兼具面向对象特征如对象和继承,同时保持语法简单。

  • 轻量便携】:最新版本的Lua仅包含约2万行C语言代码,编译后库文件大小约240K,非常适合资源有限的平台。

  • 开源免费】:Lua采用MIT Licence,可自由用于各种商业程序,无需额外费用。

Redis引入Lua脚本

自Redis 2.6版本起,引入了对Lua脚本的支持。这一创新功能通过在服务器中嵌入Lua环境,使Redis客户端能够利用Lua脚本在服务器端原子性地执行多个Redis命令,从而提升了操作的效率和一致性。

Redis中引入Lua的原因

在这里插入图片描述

Lua脚本的原子处理能力

Redis服务器严格确保Lua脚本以单线程方式原子性执行,这意味着在脚本的整个处理流程中,其执行将不会受到其他请求的干扰或打断。这种机制确保了数据的一致性和完整性,为用户提供了高度可靠的操作环境。

注意,Redis将确保整个脚本作为一个不可分割的单元执行,避免了其他请求的插入干扰,从而保证了操作的原子性。这种原子性不仅消除了竞态条件的隐患,还使我们在执行复杂逻辑时无需额外使用事务机制,简化了操作流程。

Lua减少网络开销

通过利用Redis的Lua脚本功能,我们能够实现多个请求的批量发送,从而显著减少网络往返时延,优化整体性能。

Lua脚本复用与提高效率

Redis还提供了脚本的持久化存储功能。一旦客户端发送的脚本被存储,其他客户端便可直接复用,无需重复编写或传输相同的代码逻辑。

Redis中Lua的常用命令

指令:EVAL

在Redis服务环境下,EVAL指令为用户提供了一个强大的功能,即执行自定义的Lua脚本。这些Lua脚本能够对Redis中的数据进行一系列复杂操作,从而满足了那些无法通过简单Redis命令实现的需求。

指令格式
EVAL script numkeys key [key ...] arg [arg ...]
  • 【脚本代码(script)】:它指的待执行的Lua程序代码,封装了针对Redis数据模型的操作逻辑。

脚本代码经编译后在Redis服务器端运行,旨在实现诸如事务控制、条件判断、计算密集型处理等高级功能,从而提升数据操作的效率与一致性

  • 【数据键数量(numkeys)】:它是一个整数值,它精确指明了脚本内部所引用Redis键的个数(如没有key,则为0)。

直接影响了脚本执行期间与数据库键空间的交互方式,如确保脚本原子性执行所需的WATCH/MULTI/EXEC机制能够正确识别涉及的键,以及在EVAL命令中正确解析后续的键列表

  • 【数据键列表(key [key …])】:它是按照脚本需求提供的一个变长Redis键序列,每个键均代表数据库中的一个数据的Key。例如:在脚本里面可以通过KEYS[1], KEYS[2]进行获取第一个值和第二个值,数组下标是从1开始。

Key键作为脚本执行过程中的操作对象,可能涉及到读取、更新、删除等操作。键列表的具体内容应与numkeys参数所声明的数量相匹配,确保脚本对各指定键的操作得以精准定位并执行

  • 【参数列表(arg [arg …])】:它包含了传递给Lua脚本的一系列非键值型数据输入,用于扩展脚本的灵活性与适应性,例如:在脚本里面可以通过ARGV[1],ARGV[2]进行获取第一个值和第二个值,与key相同也是下标从1开始。

参数可以是数值、字符串或其他可序列化数据类型,供脚本内部函数或逻辑根据需要进行解析与利用。参数与键列表相互独立,共同作为脚本执行的上下文环境,允许脚本在处理Redis键的同时,依据外部传入的动态信息做出决策或进行更为复杂的运算

案例介绍

举例来说,若你拥有一个Lua脚本,该脚本需要两个Key作为输入参数,分别是param1和param2。此脚本还会接受一个额外的参数值10,并将其用于比较操作。在此情境下,你可以利用EVAL指令来执行该脚本,具体使用方式如下:

127.0.0.1:6379>  EVAL "$(cat script.lua)"  2  param1 param2 10
Redis函数:call和pcall

在Lua脚本中,有两个关键函数可用于执行Redis命令,它们分别是redis.call()和redis.pcall()。这两个函数的核心功能相似,但它们在处理命令执行过程中产生的错误时采取了不同的策略。

redis.call操作

在Lua脚本中,我们巧妙地利用redis.call()方法来直接调用Redis的各项指令。举个案例,使用Lua脚本时,首先通过KEYS指令收集所需处理的键集合,随后遍历这些键执行删除操作,以此实现批量清理的目标。

-- 获取传入的需要批量删除的key的前缀  
local prefix = KEYS[1]  
-- 通过KEYS命令查询所有符合条件的key  
local keysToDelete = redis.call('keys', prefix .. '*')  
-- 如果没有找到任何key,则返回0  
if #keysToDelete == 0 then  
    return 0  
end  
-- 循环删除找到的key  
for _, key in ipairs(keysToDelete) do  
    redis.call('del', key)  
end  
-- 返回删除的key数量  
return #keysToDelete

redis.call()一旦在执行Redis命令的过程中遭遇任何异常,会即刻终止脚本的进一步执行,并反馈给用户一个富含脚本执行错误细节的响应。这种即时错误反馈机制蕴含了高度的透明性,它不仅清晰地阐述了错误发生的根本原因,还附带了详尽的上下文信息,极大便利了开发者迅速识别故障根源并采取相应修复措施,从而提升了调试效率与代码稳定性。

redis.pcall

当与Redis交互时,除了redis.call()函数,Lua脚本还提供了redis.pcall()函数。与redis.call()不同,redis.pcall()在处理过程中遇到错误时,并不会引发(raise)Lua错误,而是返回一个特殊的Lua表(table),其中包含一个名为err的字段,用于表示发生的错误详情。

pcall方法能够更加灵活地处理潜在的错误情况,避免脚本因异常而中断执行。通过使用redis.pcall(),开发者可以编写出更加健壮和容错的Redis操作逻辑。

redis-cli执行

无参数执行

redis-cli -h 地址 -p 端口 -a 密码 --eval /path/exec.lua 
多值传送示例
redis-cli -h 地址 -p 端口 -a 密码 --eval /path/exec.lua 2 "key1" "key2" , "va1" "va2"
Linux命令执行
cat 脚本路径/redis_test_data.txt | redis-cli -h 地址 -p 端口 -a 密码

最终总结

  • Redis通过单一Lua解释器执行脚本,确保脚本操作具有原子性,类似于事务处理,既不干扰其他脚本/命令,也不会被其影响,表现为对外完全完成或未开始。但注意,长时间运行的脚本可能阻塞其他客户端请求。

  • 为提升效率,虽有内置脚本缓存减少重复编译,频繁发送完整脚本作为EVAL命令参数仍非最优解,因涉及不必要的带宽消耗。为此,Redis实施了脚本缓存策略:一经执行的脚本将永久存储,后续调用可通过EVALSHA命令,直接利用SHA哈希值引用缓存中的脚本,避免重复传输,优化了带宽使用并促进了脚本的高效复用。

  • 利用Redis执行Lua脚本的操作极大地简化了许多基础的运维工作,使操作变得更为高效便捷。在开发过程中,通过执行Lua脚本的方式,我们可以有效降低对Redis的操作频率,从而最大限度地发挥其性能优势。

注意:特此声明:本文章首发文章在掘金:https://juejin.cn/post/7362805232647012378,未经允许,请勿进行侵权私自转载。

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

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

相关文章

[NSSCTF]prize_p1

前言 之前做了p5 才知道还有p1到p4 遂来做一下 顺便复习一下反序列化 prize_p1 <META http-equiv"Content-Type" content"text/html; charsetutf-8" /><?phphighlight_file(__FILE__);class getflag{function __destruct(){echo getenv(&qu…

能源监控新方案:IEC104转MQTT网关在新能源发电中的应用

需求背景 近些年&#xff0c;我国新能源产业快速发展&#xff0c;光伏、风电等新能源项目高速增长&#xff0c;新能源发电已经成为国家能源结构的重要组成部分。 打造数字化、智能化、信息化的电力物联网系统&#xff0c;实现光伏风电等新能源发电站的远程监控、远程维护是新能…

企业气候风险披露、报表词频、文本分析数据集合(2007-2022年)

01、数据介绍 企业气候风险披露是指企业通过一定的方式&#xff0c;将气候变化对其影响、自身采取的应对措施等信息披露出来。这有助于投资者更准确地评估企业价值&#xff0c;发现投资机会&#xff0c;规避投资风险。解企业在气候风险方面的关注度和披露情况。 可以帮助利益…

系统调用 int 86 的过程

该图借鉴与 Linux系统调用全过程详解-高性能服务器开发&#xff0c;向作者致敬。

WPF之创建无外观控件

1&#xff0c;定义无外观控件。 定义默认样式&#xff0c;在其静态构造函数中调用DefaultStyleKeyProperty.OverrideMetadata()。 //设置默认样式DefaultStyleKeyProperty.OverrideMetadata(typeof(ColorPicker), new FrameworkPropertyMetadata(typeof(ColorPicker))); 在项目…

【喜报】科大睿智为武汉博睿英特科技高质量通过CMMI3级评估咨询工作

武汉博睿英特科技有限公司是信息通信技术产品、建筑智慧工程服务提供商。其拥有专注于航空、政府、教育、金融等多行业领域的资深团队&#xff0c;及时掌握最新信息通信应用技术&#xff0c;深刻理解行业业务流程&#xff0c;擅于整合市场优质资源&#xff0c;积极保持与高校产…

06_电子设计教程基础篇(学习视频推荐)

文章目录 前言一、基础视频1、电路原理3、模电4、高频电子线路5、电力电子技术6、数学物理方法7、电磁场与电磁波8、信号系统9、自动控制原理10、通信原理11、单片机原理 二、科普视频1、工科男孙老师2、达尔闻3、爱上半导体4、华秋商城5、JT硬件乐趣6、洋桃电子 三、教学视频1…

日期类的模拟实现

1.定义一个日期类 有关类的定义&#xff0c;首先是需要声明共有类和私有类的成员函数和成员变量。 这里我分了三个文件写&#xff0c;分别有Date.h&#xff0c;Date.cpp&#xff0c;test.cpp using namespace std; class Date { private:int _year;int _month;int _day;publ…

IF67负载的纳米纤维膜材料

IF67负载的纳米纤维膜材料是一种结合了ZIF67&#xff08;一种沸石咪唑酯骨架结构材料&#xff09;和纳米纤维膜的材料。这种材料的制备方法通常涉及以下步骤&#xff1a; 制备含有ZIF67纳米晶体的纺丝液。 将该纺丝液与另一纺丝液&#xff08;如聚乙烯醇缩丁醛或聚氨酯的纺丝液…

firebase:一款功能强大的Firebase数据库安全漏洞与错误配置检测工具

关于firebase firebase是一款针对Firebase数据库的安全工具&#xff0c;该工具基于Python 3开发&#xff0c;可以帮助广大研究人员针对目标Firebase数据库执行安全漏洞扫描、漏洞测试和错误配置检测等任务。 该工具专为红队研究人员设计&#xff0c;请在获得授权许可后再进行安…

Science Advances|用于非侵入性表型分析的全有机透明植物电子皮肤(植物电子皮肤/柔性电子)

新加坡国立大学 Chengkuo Lee和Eunyoung Chae团队,在期刊《Science Advances》上发布了一篇题为“All-organic transparent plant e-skin for noninvasive phenotyping”的论文。论文内容如下: 一、 摘要 植物生理的实时原位监测是建立精准农业表型平台的关键。此监测的一项…

CSS优惠券、卡券样式绘制

实现左右凹陷中间有虚线效果 效果图 实现思路 从效果图可以看到这个优惠券是左右两边凹陷&#xff0c;中间还有一条虚线&#xff0c;为了封装后插槽使用方便&#xff0c;把优惠券以虚线为准分了两部分。这样布局的好处是上部分内容和下部分都可以自定义&#xff0c;不受内容限…

cmake的使用方法: 单个源文件的编译

一. 简介 经过前一篇文章的学习&#xff0c;针对不同平台下编译 .c工程时&#xff0c;为了不用针对不同平台编写&#xff08;不同标准&#xff0c;不同规范&#xff09;Makefile文件&#xff0c;提出了 cmake工具&#xff0c;cmake可以解决跨平台编译的问题。 cmake 就是针对…

JAVA面试题---WEB部分

网络通讯 TCP与UDP TCP(Transmission Control Protocol 传输控制协议)是一种面向连接(连接导向)的、 可靠的、 基于 IP 的传输层协议。 UDP 是 User Datagram Protocol 的简称&#xff0c;中文名是用户数据报协议&#xff0c;是 OSI 参考模 型中的传输层协议&#xff0c;它是…

基于光伏电站真实数据集的深度学习预测模型(Python代码,深度学习五个模型)

效果视频链接&#xff1a;基于深度学习光伏预测系统&#xff08;五个模型&#xff09;_哔哩哔哩_bilibili 界面设计 注册界面 登录界面 主界面 展示界面 1.数据集来源 The SOLETE dataset 这里分别保存了不同间隔采样时间表格 1min是以1min 间隔采集的数据集 数据集截图&…

分享自己一篇在亚马逊云科技AWS官网发的Blog技术文章

小李哥在亚马逊AWS官网&#xff0c;作为第一作者发了自己的第一篇AWS Blog文章&#xff0c;也是自己今年在AWS官网的第11篇文章。文章主要内容是描述为出海的金融企业&#xff0c;搭建满足PCI-DSS合规、FIPS 140-2 Level 3安全标准的传输中数据加密云端方案&#xff0c;主要用于…

云服务器平台Featurize--基本使用步骤与使用感受

基本介绍 图1 网址&#xff1a;Featurize 可租用实例的显示界面如图所示。 图2 在简单的注册、登录、充值之后就可以对想要的实例直接进行租赁了。 关于实例&#xff0c;这里我的理解是已经配置好一定环境的服务器。 图3 使用感受 总结一下&#xff0c;Featurize上云服务器的…

【经典算法】LeetCode112. 路径总和(Java/C/Python3/Go实现含注释说明,Easy)

作者主页&#xff1a; &#x1f517;进朱者赤的博客 精选专栏&#xff1a;&#x1f517;经典算法 作者简介&#xff1a;阿里非典型程序员一枚 &#xff0c;记录在大厂的打怪升级之路。 一起学习Java、大数据、数据结构算法&#xff08;公众号同名&#xff09; ❤️觉得文章还…

Agent AI智能体:如何借助机器学习引领科技新潮流

文章目录 &#x1f4d1;前言一、Agent AI智能体的基本概念二、Agent AI智能体的技术进步2.1 机器学习技术2.2 自适应技术2.3 分布式计算与云计算 三、Agent AI智能体的知识积累3.1 知识图谱3.2 迁移学习 四、Agent AI智能体的挑战与机遇4.1 挑战4.2 机遇 小结 &#x1f4d1;前言…

004 秒杀下单

文章目录 超卖问题方案一方案二方案三aop锁(单机锁)aop锁(单机锁)pom.xmlLockAspect.javaServiceLock.java 分布式锁Mysql分布式锁Redis分布式锁ServiceRedisLock.javaLockRedisAspect.java 下单性能优化数据一致性解决一致性问题异步同步库存 秒杀下单业务步骤: 1.数据校验(身…