如何重用将加载到 Redis 的 LUA 脚本的代码?

How to reuse code on LUA scripts that will be loaded to Redis?

目前我制作了一些 LUA 脚本加载到 Redis 来执行一些命令。有些功能对所有脚本都是通用的,比如解析内容或数据转换,我一直在脚本之间制作 copy/paste 而不是简单地重用它们。无法生成 "require",因为 Redis 将无法知道在哪里加载文件。

对于我添加的每一个脚本,维护噩梦都会变得更大!

DRY 原则如何应用于这种情况? 我想到的唯一方法是 T4 代码生成器.

我可以用这段代码创建一个 "lua" 文件:

#import "DataTransformer.lua"

T4 将尝试读取每个扩展名为 .lua 的文件并查找标签 #import。对于每个 #import 标签都会找到相应的文件并用实际代码替换该行。这样T4会自动生成copy/paste。

"DataTransformer"里面的代码应该分配给一个名为"DataTransformer"的对象,导入DataTransformer的代码可以使用对象DataTransformer.{function}.

这是否有意义,或者是否有更简单的方法来实现此目的?

您可以使用SCRIPT LOAD命令将那些功能脚本加载到缓存中,并以f_sha-code.

的形式在其他lua脚本中调用它们
  1. 将功能脚本加载到缓存

    ./redis-cli script load "redis.call('SET', KEYS[1], ARGV[1])"

    Redis returns 此脚本的 SHA 代码:xxxx-SHA-CODE-xxxx

  2. 调用函数,即在其他lua脚本中f_xxxx-SHA-CODE-xxxx

    ./redis-cli eval "f_xxxx-SHA-CODE-xxxx(KEYS[1], ARGV[1]); return redis.call('GET', KEYS[1])" 1 key val

tl;dr 不 - 没有这样的方法,使用 T4 或任何其他预处理器查找和替换是最好的方法。

细节:至少有两种未记录的方法可以做你想做的事(一种在[=19=的答案中,另一种涉及全局元表),但你真的不应该使用它们。未记录意味着它们可能无法在未来的版本中使用...

脚本应该是独立的。如果在 运行 之前加载了脚本依赖项,您真的不想开始担心。只要您使用缓存的脚本(使用 SCRIPT LOADEVALSH),除了维护所有副本之外,复制相同的有效负载并没有真正的开销。最好的方法是在部署之前将模板中的可重用元素 "injected" 放入脚本中。这样您还可以独立地对可重用对象进行单元测试。

您好,我刚刚发现 Redis 7.0 支持重用。

https://redis.io/docs/manual/programmability/functions-intro/

local function my_hset(keys, args)
...
end

redis.register_function('my_hset', my_hset)