Redis中的Lua脚本(二)

Lua脚本

创建排序辅助函数

为了防止带有副作用的函数令脚本产生不一致的数据,Redis对math库的math.random函数和math.randomseed函数进行了替换。对于Lua脚本来说,另一个可能产生不一致数据的地方是哪些带有不确定性质的命令,比如对于一个集合键来说,因为集合的排列是无序的,所以即使两个集合的元素完全相同,它们的输出结果也可能并不相同。

例子

  • 举个例子。
127.0.0.1:6379> SADD fruit apple banana cherry
(integer) 3
127.0.0.1:6379> SMEMBERS fruit
1) "banana"
2) "apple"
3) "cherry"
127.0.0.1:6379> SADD another-fruit cherry banana apple
(integer) 3
127.0.0.1:6379> SMEMBERS another-fruit
1) "apple"
2) "banana"
3) "cherry"

(高版本Redis可能已经内置了排序函数)
这个例子中的fruit集合和another-fruit集合包含的元素是完全相同的,只是因为集合添加的顺序不同,SMEMBERS命令的输出就产生了不同的结果。Redis将SMEMBERS这种在相同数据集上可能会产生不同输出的命令称为"带有不确定性的命令",这些命令包括:SINTER、SUNION、SDIFF、SMEMBERS、HKEYS、HVALS、KEYS为了消除这些命令带来的不确定性,服务器会为Lua环境创建一个排序辅助函数_redis_compare_helper,
当Lua脚本执行完一个带有不确定性的命令之后,程序会使用_redis_compare_helper作为对比函数,自动调用table.sort函数对命令的返回值做一次排序,以此来保证相同的数据集总是产生相同的输出

  • 举个例子。如果在Lua脚本中对fruit集合和another-fruit集合执行SMEMBERS命令,那么两个脚本将得出相同的结果,因为脚本已经对SMEMBERS命令的输出进行过排序了:
127.0.0.1:6379> EVAL "return redis.call('SMEMBERS', KEYS[1])" 1 fruit
1) "apple"
2) "banana"
3) "cherry"
127.0.0.1:6379> EVAL "return redis.call('SMEMBERS', KEYS[1])" 1 another-fruit
1) "apple"
2) "banana"
3) "cherry"

创建redis.pcall函数的错误报告辅助函数

服务器将为Lua环境创建一个名为_redis_err_handler的错误处理函数,当脚本调用redis.pcall函数执行Redis命令,并且被执行的命令出现错误时,_redis_err_handler_就会打印出错误代码的来源和发生错误的行数,为程序的调试提供方便。

例子

  • 举个例子。如果客户端要求服务器执行以下Lua脚本:
--1--2--3return redis.pcall('wrong command')

那么服务器将向客户端返回一个错误:

redis-cli --eval wrong-command.lua
(error) @user_script: 4: Unknown Redis command called from Lua script

其中@user_script说明这是一个用户定义的函数,而之后的4则说明出错的代码位于Lua脚本的第4行

保护Lua的全局环境

服务器将对Lua环境中的全局环境进行保护,确保传入服务器的脚本不会因为忘记使用local关键字而将额外的全局变量添加到Lua环境里面。
因为全局比那辆保护的原因,当一个脚本试图创建一个全局变量时,服务器将报告一个错误:

127.0.0.1:6379> EVAL "x = 10" 0
(error) ERR Error running script (call to f_df1ad3745c2d2f078f0f41377a92bb6f8ac79af0): @enable_strict_lua:8: user_script:1: Script attempted to create global variable 'x'

除此之外,试图获取一个不存在的全局变量也会引发一个错误:

127.0.0.1:6379> EVAL "return x" 0
(error) ERR Error running script (call to f_03c387736bb5cc009ff35151572cee04677aa374): @enable_strict_lua:15: user_script:1: Script attempted to access unexisting global variable 'x

不过Redis并未禁止用户修改已存在的全局变量,所以在执行Lua脚本的时候,必须非常消息,以免错误地修改了已存在地全局变量

127.0.0.1:6379> EVAL "redis = 10086; return redis" 0
(integer) 10086

将Lua环境保存到服务器状态的lua属性里面

在这里插入图片描述

服务器会将Lua环境和服务器状态的lua属性关联起来,如图所示.
因为Redis使用串行化的方式来执行Redis命令,所以在任何特定时间里,
最多都只会有一个脚本能够放进Lua环境里面运行,因此,整个Redis服务器只需要创建一个Lua环境即可

Lua环境协作组件

除了创建并修改Lua环境之外,Redis服务器还创建了两个用于与Lua环境进行协作的组件,它们分别是负责执行Lua脚本的Redis命令的伪客户端,以及用于保存Lua脚本的lua_scripts字典

伪客户端

因为执行Redis命令必须有相应的客户端状态,所以为了执行Lua脚本中包含的Redis命令,Redis服务器专门为Lua环境创建了一个伪客户端,并由这个伪客户端负责处理Lua脚本中包含的所有Redis命令。
Lua脚本使用redis.call函数或者redis.pcall函数执行一个Redis命令,需要完成以下步骤:

  • 1.Lua环境将redis.call函数或者redis.pcall函数想要执行的命令传给伪客户端
  • 2.伪客户端将脚本想要执行的命令传给命令执行器
  • 3.命令执行器执行伪客户端传给它的命令,并将命令的执行结果返回给伪客户端
  • 4.伪客户端接收命令执行器返回的命令结果,并将这个命令结果返回给Lua环境
  • 5.Lua环境在接收到命令结果之后,将该结果返回给redis.call函数或者redis.pcall函数
  • 6.接收到结果的redis.call函数或者redis.pcall函数会将命令结果作为函数返回值返回给脚本中的调用者

图中展示了Lua脚本在调用redis.call函数时,Lua环境、伪客户端、命令执行器三者之间的通信过程(调用redis.pcall函数时产生的通信过程也是一样的)在这里插入图片描述

例子
  • 举个例子。如图展示了Lua脚本在执行以下命令时:
127.0.0.1:6379> EVAL "return redis.call('dbsize')" 0
(integer) 3

Lua环境、伪客户端、命令执行器三者之间的通信过程如图所示
在这里插入图片描述

lua_script字典

Redis服务器为Lua环境创建的另一个协作组件是lua_scripts字典,这个字典的键为某个Lua脚本的SHA1校验和(checksum),而字典的值则是SHA1校验和对应的Lua脚本

struct redisServer {
// ...dict *lua_script;// ...
};

Redis服务器会将所有被EVAL命令执行过的Lua脚本,以及所有被SCRIPT LOAD命令载入过的Lua脚本都保存到lua_scripts字典里面。

例子
  • 举个例子,如果客户端向服务器发送以下命令:
127.0.0.1:6379> SCRIPT LOAD "return hi"
"728d9ecdcf934ba0f430b2b05f049e13041278ae"
127.0.0.1:6379> SCRIPT LOAD "return 1+1"
"a27e7e8a43702b7046d4f6a7ccf5b60cef6b9bd9"
127.0.0.1:6379> SCRIPT LOAD "return 2*2"
"4475bfb5919b5ad16424cb50f74d4724ae833e72"

那么服务器的lua_scripts字典将包含被SCRIPT LOAD命令载入的三个Lua脚本,如图所示。在这里插入图片描述

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

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

相关文章

python爬虫之环境配置(1)

一、安装python (1)下载python安装包 Python Releases for Windows | Python.org (2)傻瓜式安装python 安装成功 二、安装PyCharm (1)下载安装包 Professional:专业版(建议选择专业版&am…

前端CSS基础4(像素,颜色,字体属性大小复合属性)

前端CSS基础4&#xff08;像素&#xff0c;颜色&#xff0c;字体属性大小复合属性&#xff09; CSS代码编写位置CSS像素CSS颜色CSS常用字体属性和大小字体的复合属性 CSS代码编写位置 在HTML文件的头部使用 <head><style>/* 在这里编写CSS代码 */</style> …

VsCode调试远程服务器上面的Docker容器

第一步 VsCode 连接ssh 下载安装VsCode(Visual Studio Code)&#xff0c;首次安装会提示你安装Chinese(Simplified)中文简体&#xff0c;安装完后重新打开就是汉化界面了。在左边侧边栏找到扩展选项&#xff0c;然后安装Remote Development插件&#xff0c;里面包含了Remote S…

Redis中的Lua脚本(三)

Lua脚本 EVAL命令的实现 EVAL命令的执行过程可以分为以下三个步骤: 1.根据客户端给定的Lua脚本&#xff0c;在Lua环境中定义一个Lua函数2.将客户端给定的脚本保存到lua_scripts字典&#xff0c;等待将来进一步使用3.执行刚刚在Lua环境中定义的函数&#xff0c;以此来执行客户…

数据应用OneID:ID-Mapping Spark GraphX实现

前言 说明 以用户实体为例&#xff0c;ID 类型包含 user_id 和 device_id。当然还有其他类型id。不同id可以获取到的阶段、生命周期均不相同。 device_id 生命周期通常指的是一个设备从首次被识别到不再活跃的整个时间段。 user_id是用户登录之后系统分配的唯一标识&#xff…

【详细介绍下图搜索算法】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

NLP问答系统:使用 Deepset SQUAD 和 SQuAD v2 度量评估

目录 一、说明 二、Deepset SQUAD是个啥&#xff1f; 三、问答系统&#xff08;QA系统&#xff09;&#xff0c;QA系统在各行业的应用及基本原理 3.1 医疗 3.2 金融 3.3 顾客服务 3.4 教育 3.5 制造业 3.6 法律 3.7 媒体 3.8 政府 四、在不同行业使用QA系统的基本原理 五、关于…

使用自己训练好的模型YOLOv8进行X-AnyLabeling自动标注

目录 1. 下载项目2. 创建环境3. 运行程序3.1 自行下载和添加官方模型3.2 使用自己训练好的模型标注自己的数据集 本机环境&#xff1a;win 10&#xff0c; GPU 1. 下载项目 git clone https://github.com/CVHub520/X-AnyLabeling.git2. 创建环境 仔细查看项目的README文件 …

游游的you矩阵

题目&#xff1a; 游游拿到了一个字符矩阵&#xff0c;她想知道有多少个三角形满足以下条件&#xff1a; 三角形的三个顶点分别是 y、o、u 字符。三角形为直角三角形&#xff0c;且两个直角边一个为水平、另一个为垂直。 输入描述&#xff1a; 第一行输入两个正整数n,m&#…

Root mapping definition has unsupported parameters: [all : {analyzer=ik_max_wor

你们好&#xff0c;我是金金金。 场景 我正在使用Springboot整合elasticsearch&#xff0c;在创建索引(分词器) 运行报错&#xff0c;如下 排查 排查之前我先贴一下代码 import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; // 注意这个包SpringBootTe…

文字转语音工具:GPT-SoVITS

诸神缄默不语-个人CSDN博文目录 OpenAI官方的TTS模型我在这篇博文中给出了使用教程&#xff1a;ChatGPT 3.5 API的调用不全指南&#xff08;持续更新ing…&#xff09; - 知乎 但是OpenAI的TTS对中文支持不好&#xff0c;有一种老外说中文的美&#xff0c;所以本文介绍另一个…

自己的事情自己做:使用 Python Turtle 绘制 Python Logo

以下代码中&#xff0c;将向你展示一个有趣的程序&#xff0c;如何使用 Python Turtle 中绘制 Python Logo。Python 翻译成汉语是蟒蛇的意思&#xff0c;Python 的 Logo 也是两条缠绕在一起的蟒蛇。 import turtlepen turtle.Turtle() turtle.bgcolor("black") pe…

ins视频批量下载,instagram批量爬取视频信息【爬虫实战课1】

简介 Instagram 是目前最热门的社交媒体平台之一,拥有大量优质的视频内容。但是要逐一下载这些视频往往非常耗时。在这篇文章中,我们将介绍如何使用 Python 编写一个脚本,来实现 Instagram 视频的批量下载和信息爬取。 我们使用selenium获取目标用户的 HTML 源代码,并将其保存…

Python路面车道线识别偏离预警

程序示例精选 Python路面车道线识别偏离预警 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对《Python路面车道线识别偏离预警》编写代码&#xff0c;代码整洁&#xff0c;规则&#xff0c;易…

tsconfig.json文件常用配置

最近在学ts&#xff0c;因为tsconfig的配置实在太多啦&#xff0c;所以写此文章用作记录&#xff0c;也作分享 作用&#xff1f; tsconfig.jsono是ts编译器的配置文件&#xff0c;ts编译器可以根据它的信息来对代码进行编译 初始化一个tsconfig文件 tsc -init配置参数解释 …

HZNUCTF第五届校赛实践赛初赛 Web方向 WriteUp

ezssti 很简单的ssti 源码给了&#xff0c;调用Eval即可执行命令 package mainimport ("fmt""net/http""os/exec""strings""text/template" )type User struct {Id intName stringPasswd string }func (u User) Ev…

Python学习从0开始——项目一day01爬虫

Python学习从0开始——项目一day01爬虫 一、导入代码二、使用的核心库三、功能测试3.1初始代码3.2新建文件3.3代码调试 四、页面元素解析4.1网页4.2修改代码4.3子页面4.4修改代码 一、导入代码 在Inscode新建一个python类型的项目&#xff0c;然后打开终端&#xff0c;粘贴以下…

《七》布局QLayout类

QLayout简介 QLayout是由具体类 QBoxLayout、QGridLayout、QFormLayout 和 QStackedLayout继承的抽象基类。 对于 QLayout子类或 QMainWindow的用户&#xff0c;很少需要使用 QLayout 提供的基本功能&#xff0c;例如 setSizeConstraint() 或 setMenuBar()。Qt 布局系统提供了…

程序员购车指南

哈喽大家好&#xff0c;我是咸鱼。 爱车可以说是大部分男人的天性&#xff0c;而我对汽车的热情却远不及对手表的钟爱&#xff08;痴迷劳力士&#xff09;。以至于我的朋友掏出车钥匙指着上面的苹果树标志跟我介绍奔驰 AMG 系列的强劲性能和马力时&#xff0c;我只能尽量假装自…

【三维Dvhop定位】基于麻雀搜索算法的多通信半径和跳距加权的三维Dvhop定位算法【Matlab代码#81】

文章目录 【可更换其他算法&#xff0c;获取资源请见文章第6节&#xff1a;资源获取】1. Dvhop定位算法2. 麻雀搜索算法3. 多通信半径和跳距加权策略3.1 多通信半径策略3.2 跳距加权策略 4. 部分代码展示5. 仿真结果展示6. 资源获取 【可更换其他算法&#xff0c;获取资源请见文…