【问题标题】:Redis how to reduce lua copy-pasteRedis如何减少lua复制粘贴
【发布时间】:2015-10-28 02:51:32
【问题描述】:

我正在为 lua 中的 redis 编写一些逻辑,几乎我的每个脚本都有一些共同点,将其移出到共享函数会非常方便,但是

  1. redis 不能使用 lua 的 require 语句
  2. 官方不能调用其他redis函数(见:https://stackoverflow.com/a/22599862/1812225

例如,我到处都有这个 sn-p

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 命令时不能轻易移动到客户端,并且作为事务的一部分工作

谢谢!

【问题讨论】:

  • 假设有可能让这个常见的 sn-p “共享” - 你真的想使用它吗?换句话说,这是一项需要多次完成的平凡任务……将其推送到 Lua 脚本中意味着您将使用 Redis 数据库中的资源来执行可以在其他地方完成的事情。我并不是说这是错误的,但根据经验,我尽量将这种类型的逻辑保留在数据库之外。
  • 关于这个 sn-p 你可能是对的@itamar-haber。但是我有另一种情况,当我需要用条件逻辑做事时,一遍又一遍地触发redis命令......它不能轻易移动到客户端
  • 另一方面,我可能应该创建另一个具有重复步骤的脚本,并在MULTI 中使用它们,即MULTI EVALSHA EVALSHA ... 从带宽的角度来看,这似乎并不理想,但不应该成为一个大问题
  • 每种情况都不同 :) 基本上选项是 a) 复制粘贴 b) 使用未记录的 f_ 方法或 c) 围绕 Redis 的全局保护“破解”。我觉得最安全的是(a)
  • @ItamarHaber 两件事。 a) 什么是未记录的 f_ 方法? b) 为什么在这里使用 redis-lua-debugger 使用的技巧? (github.com/RedisLabs/redis-lua-debugger)(当然要考虑到slave不能自己运行脚本的限制)。

标签: lua redis


【解决方案1】:

“黑客”#1

在你SCRIPT LOAD 之后,你会得到一个可以与EVALSHA 一起使用的sha1 哈希。可以使用相同的 sha1 值从 inside 另一个脚本调用该脚本 - 只需调用函数 f_<sha1>。也就是说,以这种方式传递 KEYS/ARGV 结构的方式存在一些差异。

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

教我这一点的功劳归于 Josiah Carlson 博士,而他又将功劳归功于其他人 (IIRC Fritzy)。有关更多信息,请查看他的 lua-call Python 包装器:https://github.com/josiahcarlson/lua-call

“黑客”#2

Redis 对 Lua 进行沙盒处理,并对其设置了一些限制以保持理智。你可以绕过其中一些,例如访问 _G 并在那里定义您的实用程序函数,以便所有脚本都可以使用它(就像我对 https://github.com/redislabs/redis-lua-debugger 所做的那样)。

但是,这也有很大的风险 - 除了潜在的复制问题之外,这种用法未经测试,因此可能导致未定义的行为(我设法用我的小脚本崩溃了很多实例;))。

附言

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

【讨论】:

  • 感谢您的详细回复。我想知道最终是否会添加一种在 Redis 实例上提供实用程序代码的标准化方法。我预见自己会在许多脚本中一遍又一遍地使用一些代码(redis.log 包装器、underscore.lua 等库等)。
  • Redis 社区始终欢迎建议/想法/公关贡献者 - 为什么不展示您的案例并开始讨论?
  • Hack #1 实际上是否使用了未记录的行为? sha1 是客户端获取已加载脚本句柄的 方式。 (这是调用 f_ 的问题吗?)
  • @tim 确切地说,f_sha1 是一个内部实现,你不能指望它在未来的版本中保持不变。
猜你喜欢
  • 1970-01-01
  • 2022-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-23
  • 2021-02-10
  • 1970-01-01
相关资源
最近更新 更多