在Redis中,是否可以调用其他Lua脚本中定义的Lua函数?
我试图在不使用 local 关键字声明函数的情况下,然后从另一个脚本调用该函数,但是当我运行该命令时,它会给我一个错误。
test = function ()
return 'test'
end
#从其他脚本
test()
编辑:
我无法相信我还没有这个答案。我将包括更多关于我的设置的细节。
我正在使用 node 和 redis-scripto 包将脚本加载到 redis 中。这是一个例子。
var Scripto = require('redis-scripto');
var scriptManager = new Scripto(redis);
scriptManager.loadFromDir('./lua_scripts');
var keys = [key1, key2];
var values = [val];
scriptManager.run('run_function', keys, values, function(err, result) {
console.log(err, result)
})
和 lua 脚本。
-- ./lua_scripts/dict_2_bulk.lua
-- 将字典表转换为批量回复表
dict2bulk = function (dict)
local result = {}
for k, v in pairs(dict) do
table.insert(result, k)
table.insert(result, v)
end
return result
end
-- run_function.lua
return dict2bulk({test = 1})
抛出以下错误。
[错误:ERR运行脚本错误(调用f_d06f7fd783cc537d535ec59228a18f70fccde663):@ enable_strict_lua:14:user_script:1:脚本尝试访问不存在的全局变量'dict2bulk']未定义
我要反对被接受的回答,因为被接受的回答是错误的。
尽管您不能明确定义命名函数,但是您可以调用任何可用EVALSHA调用的脚本。更具体地说,您通过SCRIPT LOAD或隐式EVAL明确定义的所有Lua脚本都在全局Lua命名空间中可用于f_<sha1 hash>(直到/除非您调用SCRIPT FLUSH),您可以随时调用它们。
你遇到的问题是函数被定义为不接受参数,而KEYS和ARGV表实际上是全局的。因此,如果您希望在Lua脚本之间进行通信,您需要操纵KEYS和ARGV表,或者您需要使用标准Redis keyspace在函数之间进行通信。
127.0.0.1:6379> script load "return {KEYS[1], ARGV[1]}"
"d006f1a90249474274c76f5be725b8f5804a346b"
127.0.0.1:6379> eval "return f_d006f1a90249474274c76f5be725b8f5804a346b()" 1 "hello" "world"
1) "hello"
2) "world"
127.0.0.1:6379> eval "KEYS[1] = 'blah!'; return f_d006f1a90249474274c76f5be725b8f5804a346b()" 1 "hello" "world"
1) "blah!"
2) "world"
127.0.0.1:6379>
所有这些说法都违反了规范,并且在尝试在Redis集群场景中运行此操作时可能以奇怪的方式停止工作。
因为我不会轻易放弃,所以我开发了一个包,可以实现简单的内部调用语义。这个(适用于 Python 的)包可以在 GitHub 上 找到。
长话短说,它使用 ARGV 作为调用堆栈,将 KEYS/ ARGV 的引用转换为 _KEYS 和 _ARGV,在内部使用 Redis 作为名称->哈希映射,并将 CALL.<name>(<keys>, <argv>) 转换为一个表追加 + Redis 查找 + Lua 函数调用。
METHOD.txt 文件描述了发生的事情,我用来转换 Lua 脚本的所有正则表达式都可以在 lua_call.py 中找到。欢迎使用我的语义。
函数注册表的使用使这在 Redis 群集或任何其他多分片设置中非常不可能工作,但对于单主应用程序,它应该在可预见的未来内可行。
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
重要通知: 请参考Josiah的下面的回答。我的回答证明是 错误 或至少是 不完整 的。 当然这使我非常高兴,这使得Redis更加灵活。
我的不正确/不完整的回答:
我很确定这是不可能的。 您不允许使用全局变量(阅读文档),并且由Redis Lua引擎生成的脚本本身具有本地和临时作用域。
Lua函数自动在幕后设置“写入”标志,如果它们执行任何写操作,则会启动事务。 如果您级联Lua调用,则Redis中的簿记将变得非常麻烦,特别是当级联在Redis从服务器上执行时。 这就是为什么
EVAL和EVALSHA故意未在Lua脚本内作为有效的Redis调用出现的原因。调用您正在尝试执行的已“加载”的Lua函数也是一样的。 如果在第一个脚本的加载和第二个脚本的执行之间重启从服务器会发生什么?我们如何克服这种限制:
不要使用
EVAL,只使用SCRIPT LOAD和EVALSHA。 将SHA1存储在redis哈希集中。我们在我们的版本控制系统中自动化了这个过程,因此已提交的Lua脚本自动在Redis主服务器中以哈希集的形式存储其SHA1校验和并赋予逻辑名称。客户端不能使用EVAL(在从服务器上;我们在配置中禁用了EVAL+LOAD)。但是,客户端可以请求下一步的SHA1。 几乎所有我们的Lua函数都返回下一步的SHA1。
希望这有所帮助,TW。