我正在设置一个将同时使用 Redis 和 APCu 的 PHP 标记缓存实现。 由于 APC 是键值存储,我将使用 Redis 建立键标签关系并与 APC 上的每个网络服务器同步。
我目前的问题只涉及 Redis。 您可能知道实现方式,但要弄清楚: key 可以具有与之关联的标签。在稍后的某个时间点,您可以通过某些标签删除缓存的 key 。 有很多键,没有那么多标签,键和标签之间存在 n 对 n 的关系。
set(key, value, tags)
包括:
SET key value
foreach tag in tags
SADD tag key
因为设置后不需要检索或更改标签,所以我只需要保持标签与键的关系。
deleteByTag(tags)
是
keys = SUNION tag1 tag2 tag3...
DEL key1 key2 key2...
为了加快速度,我创建了 2 个简单的 lua 脚本,我将脚本加载并调用 EVALSHA。
Lua 设置脚本:
redis.call('set', KEYS[1], KEYS[2])
for _, tag in pairs(ARGV) do
redis.call('sadd', tag, KEYS[1])
end
调用
EVALSHA setHash 2 key value tag1 tag2 tag3...
我遇到问题的 deleteByTag 脚本如下所示:
redis.call('del', unpack(redis.call('sunion', unpack(ARGV))))
redis.call('del', unpack(ARGV))
调用
EVALSHA deleteByTagHash 0 tag1 tag2 tag3...
一切正常,除非 redis.call('sunion', unpack(ARGV))
返回大量键。似乎 Lua 对一个方法可以拥有的参数数量有一个硬性限制。在我的环境中是 8000。
我想知道是否有办法通过标签清除 key 但避免:
- (1) 往返服务器并将 key 来回传输给客户端
- (2) for-each on keys。我尝试使用这个修改后的脚本,它比 (1) 慢
这里是 (2) 运行速度不够快:
for _, key in pairs(redis.call('sunion', unpack(ARGV))) do
redis.call('del', key)
end
redis.call('del', unpack(ARGV))
最佳答案
我几乎可以肯定,您可以通过更改 8000
来增加该数字 ( LUAI_MAXCSTACK
)您环境中的值(value) luaconf.h
并重建它(Lua 环境)。
正如您已经注意到的那样,默认值是:
/*
@@ LUAI_MAXCSTACK limits the number of Lua stack slots that a C function
@* can use.
** CHANGE it if you need lots of (Lua) stack space for your C
** functions. This limit is arbitrary; its only purpose is to stop C
** functions to consume unlimited stack space. (must be smaller than
** -LUA_REGISTRYINDEX)
*/
#define LUAI_MAXCSTACK 8000
只是它有点像色情片。
如何使用表并遍历 table.concat()
block <=8000
key ?
关于lua - 如何避免 Lua 脚本限制中的 Redis 调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19202367/