我试图声明一个没有local关键字的函数,然后从另一个脚本调用该函数,但是当我运行命令时它会给我一个错误。
test = function ()
return 'test'
end
# from some other script
test()
编辑:
我无法相信我仍然没有答案。我将详细介绍我的设置。
我正在使用带有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
-- turns a dictionary table into a bulk reply table
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 })
引发以下错误。
[Error: ERR Error running script (call to f_d06f7fd783cc537d535ec59228a18f70fccde663): @enable_strict_lua:14: user_script:1: Script attempted to access unexisting global variable 'dict2bulk' ] undefined
答案 0 :(得分:5)
我会接受已接受的答案,因为接受的答案是错误的。
虽然您无法明确定义命名函数,但可以调用可以使用EVALSHA
调用的任何脚本。更具体地说,您通过SCRIPT LOAD
或通过EVAL
隐式定义的所有Lua脚本都可以在f_<sha1 hash>
的全局Lua命名空间中使用(除非您调用SCRIPT FLUSH
}),你可以随时打电话。
您遇到的问题是函数被定义为不带参数,KEYS
和ARGV
表实际上是全局变量。因此,如果您希望能够在Lua脚本之间进行通信,则需要修改KEYS
和ARGV
表,或者需要使用标准Redis键空间来进行函数之间的通信。
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集群场景中运行它,完全有可能以奇怪的方式停止工作。
答案 1 :(得分:1)
重要提示:请参阅下面的Josiah的回答。我的答案结果是错误或至少不完整。这让我非常高兴,这让Redis变得更加灵活。
我的错误/不完整答案:
我很确定这是不可能的。您不能使用全局变量(阅读docs),并且脚本本身由Redis Lua引擎获取本地和临时范围。
如果Lua函数执行任何写操作,它们会在幕后自动设置“写入”标志。这会启动一个事务。如果您级联Lua调用,Redis中的簿记将变得非常麻烦,尤其是在Redis从站上执行级联时。这就是为什么EVAL
和EVALSHA
有意无法作为Lua脚本中的有效Redis调用而可用的原因。调用已经尝试执行的已经“加载”的Lua函数也是如此。如果在第一个脚本的加载和第二个脚本的exec之间重新启动从属设备会发生什么?
我们如何克服这一限制:
请勿使用EVAL
,仅使用SCRIPT LOAD
和EVALSHA
。
将SHA1存储在redis哈希集中。
我们在版本控制系统中对此进行了自动化,因此提交的Lua脚本会自动获取存储在Redis主服务器中的SHA1校验和,并使用逻辑名称存储在哈希集中。客户端无法使用EVAL(在从服务器上;我们在配置中禁用了EVAL + LOAD)。但是客户端可以在下一步请求SHA1。几乎所有的Lua函数都为下一次调用返回一个SHA1。
希望这有帮助,TW
答案 2 :(得分:0)
因为我不能单独留下足够好的东西,所以我构建了一个允许简单内部调用语义的包。包(适用于Python)可用on GitHub。
长话短说,它使用ARGV
作为调用堆栈,将KEYS
/ ARGV
引用转换为_KEYS
和_ARGV
,使用Redis作为名称 - &GT;内部哈希映射,并将CALL.<name>(<keys>, <argv>)
转换为表追加+ Redis查找+ Lua函数调用。
METHOD.txt
文件描述了发生了什么,我用来翻译Lua脚本的所有正则表达式都可以在lua_call.py
中找到。随意重用我的语义。
使用函数注册表使得非常不太可能在Redis集群或任何其他多分片设置中工作,但对于单主应用程序,它应该在可预见的未来工作。