《Redis设计与实现》第二十章总结一:Lua脚本之总述

本文总结了《Redis设计与实现》第二十章关于Lua脚本的内容,包括如何创建和修改Lua环境,以及Lua环境在Redis中的协作组件。重点讨论了EVAL和EVALSHA命令,以及脚本复制的策略,确保在主从复制中脚本的一致性。
摘要由CSDN通过智能技术生成

20 Lua脚本

作用:
通过在服务器嵌入Lua环境,客户端可以使用Lua脚本,直接在服务器端原子性地执行多个Redis命令

EVAL:可以直接对输入的脚本进行求值
在这里插入图片描述
EVALSHA:可以根据脚本的SHA1校验和来对脚本进行求职;要求校验和对应的脚本至少被EVAL执行过一次或曾被SCRIPT LOAD 命令载入过
在这里插入图片描述

20.1 创建并修改Lua环境

过程:8步
在这里插入图片描述
接下来逐一介绍这些步骤

20.1.1 创建Lua环境

调用Lua的C API函数lua_open,创建一个新的Lua环境

20.1.2 载入函数库

在这里插入图片描述

20.1.3 创建Redis全局表格

创建一个redis表格(table)并将其设为全局变量,其包含的函数有:
在这里插入图片描述
通过redis.call和redis.pcall函数,用户可以直接在Lua脚本中执行Redis命令:
在这里插入图片描述

20.1.4 使用Redis自制的随机函数来替换Lua原有的随机函数

原因:防止带有副作用的函数令脚本产生不一致的数据
在这里插入图片描述
使用自制函数替换了math库的math.random和math.randomsees,两个替换函数有以下特征:
在这里插入图片描述

20.1.5 创建排序辅助函数

原因:对于Lua脚本,除了20.1.4,另一个可能产生不一致数据的地方是那些带有不确定性质的命令

例子:set
在这里插入图片描述
在相同数据集上可能会产生不同输出的命令称为”带有不确定性的命令“,如SMEMBERS,还有:
在这里插入图片描述
解决:
在这里插入图片描述
例子:
在这里插入图片描述

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

内容:
在这里插入图片描述

20.1.7 保护Lua的全局环境

内容:
在这里插入图片描述
即当脚本试图创建一个全局变量或获取一个不存在的全局变量,都会报错;不过可以修改

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

将Lua环境和服务器状态的lua属性关联起来:
在这里插入图片描述
只需要创建一个Lua环境的原因:
在这里插入图片描述

20.2 创建Lua环境协作组件

创建两个组件:一个是负责执行Lua脚本中的Redis命令的伪客户端,一个是用于保存Lua脚本的lua_scripts字典

20.2.1 伪客户端

作用:
在这里插入图片描述
使用redis.call函数或redis.pcall函数执行一个redis命令的流程如下:
在这里插入图片描述

20.2.2 lua_scripts字典

键为某个Lua脚本的SHA1校验和,值为SHA1校验和对应的Lua脚本:
在这里插入图片描述
例子:
在这里插入图片描述
作用:实现SCRPIT EXISTS命令(键,20.5.2)和脚本复制功能(值,20.6.2.3)

20.3、20.4、20.5与命令实现有关,请看《Redis设计与实现》第二十章总结二:Lua脚本之命令实现

20.6 脚本复制

当服务器运行在复制模式之下时,具有写性质的脚本命令也会被复制到从服务器

命令为EVAL、SCRIPT FLUSH、SCRIPT LOAD、EVALSHA

20.6.1 EVAL、SCRIPT FLUSH、SCRIPT LOAD命令的复制方法

与复制其他普通命令相同,直接传播给从服务器:
在这里插入图片描述

  • EVAL

效果:主从服务器都会执行相同的Lua脚本

  • SCRIPT FLUSH

效果:主从服务器都会重置自己的Lua环境,并清空自己的脚本字典

  • SCRIPT LOAD

效果:主从服务器都会载入相同的Lua脚本

20.6.2 EVALSHA命令的复制方法

不能直接传播命令的原因:
1.可能主从服务器的lua_scripts字典不相同,主服务器能够执行的,从服务器可能执行不了,出现脚本未找到错误;出现在从服务器开始复制主服务器之前,主服务器已执行过某些脚本的场景
2.多个从服务器之间载入Lua脚本的情况也可能各有不同,一个从服务器成功,不代表其他的从服务器也能成功;出现在不同从服务器开始复制主服务器的时间不同的场景

解决:涉及lua_scripts字典和repl_scriptcache_dict字典
在这里插入图片描述

20.6.2.1 判断传播EVALSHA命令是否安全的方法

主服务器使用redisServer的repl_scriptcache_dict字典来记录自己已经将哪些脚本传播给了所有从服务器:
在这里插入图片描述
键为Lua脚本的SHA1校验和,值全为null

当EVALSHA命令的校验和在repl_scriptcache_dict字典中时,主服务器可以向从服务器传播此EVALSHA命令;
如果只存在于lua_scripts字典而不存在于repl_scriptcache_dict字典中时,那么至少会有一个从服务器遇上脚本未找到错误

20.6.2.2 清空repl_scriptcache_dict字典

在这里插入图片描述

20.6.2.3 EVALSHA命令转换称EVAL命令的方法

通过EVALSHA指定的SHA1校验和以及lua_scripts字典保存的Lua脚本进行转换:
在这里插入图片描述
场景:
在这里插入图片描述
之后,针对此校验和,就可以直接使用EVALSHA命令了:
在这里插入图片描述

20.6.2.4 传播EVALSHA命令的方法

主服务执行EVALSHA之后,将判断此命令给定的校验和是否存在于repl_scriptcache_dict字典中,来决定传播EVAL还是EVALSHA:若存在,则传播EVALSHA;若不存在,则转换成等价的EVAL再传播,然后将此校验和添加到主服务器的repl_scriptcache_dict字典中

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值