Redis如何减少lua的复制粘贴

我正在编写Redis内部的Lua逻辑,几乎每个脚本都有些共同的东西,将它们移动到共享函数中会非常方便,但存在以下问题:

  1. Redis无法使用Lua的require语句
  2. 不能正式调用其他Redis功能(参见:https://stackoverflow.com/a/22599862/1812225)

例如,我在每个地方都有这段代码:

local prefix = "/" .. type
if typeId then
    prefix = prefix .. "(" .. typeId .. ")"
end

我正在考虑在将脚本发送到Redis之前进行某些后处理,但这似乎有些过度了...

解决/减少这个问题的最佳实践是什么?

更新代码示例:

local registryKey = "/counters/set-" .. type
local updatedKey = "/counters/updated/set-" .. type
if typeId then
    redis.call("SAdd", updatedKey, name .. ":" .. typeId)
    redis.call("SAdd", registryKey, name .. ":" .. typeId)
else
    redis.call("SAdd", updatedKey, name)
    redis.call("SAdd", registryKey, name)
end

这是另一个代码示例,无法简单地移动到客户端,因为它调用Redis命令并作为事务的一部分工作。

谢谢!

点赞
用户3160475
用户3160475

"Hack" #1"

在使用 SCRIPT LOAD 之后,你会得到一个 sha1 值,你可以使用它来调用 EVALSHA。同样的,你也可以在另一个脚本中使用相同的 sha1 值来调用这个脚本 - 只需调用函数 f_<sha1>。然而,在使用该方法时,传递 KEYS/ARGV 结构的方式有所不同。

请注意,这是未记录的行为,这意味着在将来的 Redis 版本中,该行为可能会发生变化。

学会这个技巧的功劳归功于 Josiah Carlson 博士,他将其归功于另一个人(如果我没记错的话,是 Fritzy)。想要了解更多信息,请查看他的lua-call Python wrapper: https://github.com/josiahcarlson/lua-call

“Hack”#2

Redis 对 Lua 进行了沙箱操作并施加了一些限制以保持其健康。你可以绕过其中的一些限制,例如访问 _G 并在那里定义你的实用程序函数,这样它将对所有脚本都可用(就像我使用 https://github.com/redislabs/redis-lua-debugger 一样)。

然而,这也相当危险 - 除了潜在的复制问题,该用法也未经过测试,并且因此可能导致未定义的行为(我的小脚本成功崩溃了不少实例 ;))。

附加内容

这两种技巧都需要额外的管理工作,以确保这些“全局”脚本在任何其他脚本调用它们之前都已加载。

2015-08-06 18:06:05