我正在尝试显示所有看起来像'myprefix:*'的键及其TTL。 然后,我可以允许管理员使密钥过期,或者“触摸它”(即在到期时加一小时)。
我可以使用redisClient.keys('myprefix:*', (err, keys) => {})
来获取密钥,但redisClient.ttl
命令只接受单个密钥,而不是数组。我不想迭代数组并发送n ttl
个命令。
我知道我可以使用multi
发送ttl
命令的事务,但我想知道是否有更好的方法(在JavaScript中 - 不是shell )用一两个命令获取所有密钥及其TTL?
答案 0 :(得分:1)
当Redis嵌入Lua interpreter时,解决方案就是创建一个像这样的Redis Lua脚本:
local keys = redis.call('keys','myprefix:*')
local result = {}
for i,k in ipairs(keys) do
local ttl = redis.call('ttl', k)
result[i] = {ttl}
end
return result
使用ioredis,您可以简化NodeJS中Redis Lua脚本的声明:
var Redis = require('ioredis');
var redis = new Redis();
// This will define a command getTtls:
redis.defineCommand('getTtls', {
numberOfKeys: 1,
lua: "local keys = redis.call('keys', KEYS[1]..':*')\n local result = {}\n for i,k in ipairs(keys) do \n local ttl = redis.call('ttl', k)\n result[i] = {ttl}\n end\n return result"
});
// now invoke this new command, giving the prefix as a parameter
redis.getTtls('myprefix', function (err, result) {
console.log(result);
});
脚本在NodeJS应用程序中定义,但由Redis执行。
不要忘记在生产中使用KEYS命令通常是一个坏主意,因为它在一次操作中扫描整个数据库,因此使得Redis实例在可能相当长的时间内对其他请求没有响应(取决于关于数据库中的键数)。如果在您的用例中存在问题,您可能希望改为使用SCAN命令。
答案 1 :(得分:1)
最后使用multi
。我确实理解使用keys
和multi
都非常不推荐用于制作。但我现在正在处理的密钥数量非常少(少于10个)。
使用keys
+ multi
获取N个密钥的ttl
会导致2次网络旅行,而不是N + 1.
随着它的发展,我会重新评估解决方案。如果有人需要,我在下面发布了我的代码:
let getKeys = prefix => {
return new Promise((resolve, reject) => {
redisClient.keys(`${prefix}:*`), (err, keys) => {
if(err) {
reject(err)
}
else {
let multi = redisClient.multi();
keys.forEach(k => multi.ttl(k));
multi.exec((err2, ttls) => {
if(err2) {
reject(err2);
}
else {
let result = keys.map((k, i) => ({key: k.replace(`${prefix}:`, ''), ttl: ttls[i]}));
resolve(result);
}
});
}
});
});
};
这会产生一个数组:
[ { key: '05460a69f7c0d313b7edfcca4f267cee', ttl: 3034 },
{ key: 'b1065bfa82408a10e2d2d0a50df1eef9', ttl: 3031 },
{ key: 'c3aeced2ef08f1c728f0b367c50a962a', ttl: 3019 } ]