有没有可能在redis中调用其他lua脚本中定义的lua函数?

我试图声明一个没有本地关键字的函数,然后从另一个脚本调用这个函数,但是当我运行这个命令时,它给了我一个错误。

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 

重要通知:请参阅下面的Josiah的回答。 我的答案是错误的,或者至less是不完整的 。 这让我非常开心,这让Redis更加灵活。

我的错误/不完整的答案:

我很确定这是不可能的。 您不能使用全局variables(阅读文档 ),脚本本身通过Redis Lua引擎获取本地和临时范围。

如果执行任何写操作,Lua函数会在幕后自动设置“写入”标志。 这开始一个交易。 如果您将Lua调用级联,则Redis中的簿记将变得非常麻烦,尤其是在级联在Redis从站上执行时。 这就是为什么EVALEVALSHA在Lua脚本中故意不能作为有效的Redis调用提供的原因。 调用已经加载的Lua函数也是一样的。 如果在第一个脚本的加载和第二个脚本的执行之间重新启动从站,会发生什么?

我们做什么来克服这个限制:

不要使用EVAL ,只能使用SCRIPT LOADEVALSHA 。 将SHA1存储在redis哈希集合中。

我们在我们的版本控制系统中自动执行了这个操作,所以一个确定的Lua脚本自动将它的SHA1校验和存储在Redis master中,并且使用一个逻辑名称作为哈希集合。 客户端不能使用EVAL(在从属设备上,我们在configuration中禁用了EVAL + LOAD)。 但客户可以要求下一步的SHA1。 几乎我们所有的Lua函数都会为下一个调用返回一个SHA1。

希望这有助于TW

我将违背公认的答案,因为接受的答案是错误的。

虽然无法明确定义命名函数,但您可以调用可以使用EVALSHA调用的任何脚本。 更具体地说,所有通过SCRIPT LOAD或通过EVAL隐式定义的Lua脚本都可以在全局Lua名称空间f_<sha1 hash> (直到/除非调用SCRIPT FLUSH ),您可以随时调用它。

你遇到的问题是函数被定义为不带参数, KEYSARGV表实际上是全局的。 所以,如果你想能够在Lua脚本之间进行通信,你需要修改你的KEYSARGV表,或者你需要使用标准的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)“你好”
 2)“世界”
 127.0.0.1:6379> eval“KEYS [1] ='blah!'; return f_d006f1a90249474274c76f5be725b8f5804a346b()”1“hello”“world”
 1)“blah!”
 2)“世界”
 127.0.0.1:6379>

所有这一切都说明了这完全违反了规范,如果您尝试在Redis集群scheme中运行此操作,完全可能以奇怪的方式停止工作。

因为我不是一个人,所以我build立了一个允许简单的内部调用语义的包。 该包(用于Python) 在GitHub上可用 。

长话短说,它使用ARGV作为调用堆栈,将KEYS / ARGV引用翻译为_KEYS_ARGV ,在内部使用Redis作为名称 – >哈希映射,并将CALL.<name>(<keys>, <argv>)转换为一个表追加+ Redis查找+ Lua函数调用。

METHOD.txt文件描述了发生的事情,我用来翻译Lua脚本的所有正则expression式都可以在lua_call.pylua_call.py 。 随意重新使用我的语义。

functionregistry的使用使得在Redis集群或任何其他多分片设置中不太可能工作,但是对于单主应用程序,它应该在可预见的未来工作。