专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

关于Redis中Lua的工作原理

:::tip

Redis在2.6版本开始引入了对Lua脚本的支持,通过在服务器嵌入Lua环境,Redis客户端可以使用Lua脚本直接在服务器端原子地执行多个Redis命令

:::

关于Lua的命令

执行lua脚本

EVAL script numkeys key [key …] arg [arg …]

通过lua脚本的sha1校验和执行lua脚本

EVALSHA sha1 numkeys key [key …] arg [arg …]

加载lua脚本到redis内存中

SCRIPT LOAD script

通过sha1校验和检查脚本是否存在于redis内存中

SCRIPT EXISTS sha1

清空redis内存中缓存的lua脚本

SCRIPT FLUSH

停止lua的执行

SCRIPT KILL

内部工作原理

为了在Redis服务器中执行Lua脚本,Redis服务器内嵌了一个Lua环境

60_1.png

因为Redis使用串行化的方式来执行Redis命令,所以在任何时间里,最多只有一个脚本能被放进Lua环境里执行,因此,只需要创建一个Lua环境即可

伪客户端

因为执行Redis命令必须有相应的客户端,所以Redis服务器专门为Lua环境创建看一个伪客户端,由这个伪客户端负责处理Lua脚本中包含的所有Redis命令

下图是通过lua脚本执行redis命令时的流程

60_2.png

lua_scripts字典

除了伪客户端之外,Redis服务器还创建了一个lua_scripts字典,键为某个lua脚本的SHA1校验和,值为对应的lua脚本内容

60_3.png

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

举个

客户端执行EVAL ‘return hi’ 命令

60_4.png

Redis服务器首先计算Lua脚本内容的sha1校验和,然后判断是否已存在,然后存进lua_scripts字典中

60_5.png

60_6.png

接着在Lua环境中创建一个函数,函数名为f_加上Lua脚本的sha1校验和,函数内容为Lua脚本的内容

60_7.png

然后调用Lua环境中刚刚创建的函数,即完成了EVAL指令对Lua脚本的执行

后续用户可以通过EVALSHA命令通过sha1校验和执行Lua脚本,实际上也就是通过sha1校验和找到Lua环境中对应的函数然后执行

lua_scripts的作用

1、 后续lua的执行可以通过EVALSHA 传递 sha1校验和的方式执行,避免每次执行时都需要将完整的Lua脚本内容发送给Redis服务器
2、 主从模式下实现脚本复制

脚本复制

通过上面的描述后发现lua_scripts字典存的lua脚本的内容好像没有用到,其实它的用途是用在主从复制时脚本的复制上

跟其他普通的Redis命令一样,当服务器运行在复制模式下时,具有写性质的脚本命令也会被复制到从节点,包括

1、 EVAL
2、 EVALSHA
3、 SCRIPT LOAD
4、 SCRIPT FLUSH

其中EVAL,SCRIPT LOAD和SCRIPT FLUSH可以直接复制给从节点

60_8.png

但是EVALSHA命令的复制却复杂一点

因为EVALSHA的执行需要Redis服务器提前将Lua脚本缓存到内存中,否则会执行失败

如果直接将EVALSHA命令复制给从节点,可能会出现以下两种情况而执行失败

60_9.png

所以为了解决这个问题,主节点需要

1、 判断哪些Lua脚本在所有从节点已经加载过
2、 如果没有加载过,需要通过把Lua脚本加载到从节点中

所以Redis服务器中维护了一个repl_scriptcache_dict的字典,键为某个Lua脚本的sha1校验和,值为null

60_10.png

当一个sha1校验和出现在这个字典时,说明这个校验和对应的Lua脚本已经传播给所有从节点,主节点可以直接向从节点传播EVALSHA命令,而不必担心从节点会出现脚本未找到的错误

当一个sha1校验和没有出现在这个字典时,说明直接复制EVALSHA命令会出错,所以需要将EVALSHA命令转换成EVAL命令,然后再复制给从节点执行。EVALSHA命令转换成EVAL命令就是通过sha1校验和从lua_scripts字典中找到Lua脚本的内容来实现的

当一个新的从节点加入进来的时候,需要将repl_scriptcache_dict全部清空,因为随着新的从节点的加入,字典里面记录的脚本已经不再被所有从服务器加载过了

参考

Redis设计与实现

文章永久链接:https://tech.souyunku.com/26017

未经允许不得转载:搜云库技术团队 » 关于Redis中Lua的工作原理

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们