@MohammedAl-Mahdawi 我在我的一个项目中有一个类似的用例,并使用 ioredis 提供的scanStream
实现。 这基本上是使用scan
命令的更简单方法: https :
如果您像前面提到的@stockholmux一样使用SCAN
和UNLINK
,您应该能够在不阻塞 Redis 的情况下删除任意数量的键。
@dirkbonhomme 非常感谢您的帮助,我真的很感激。
我听从了您的建议并使用了 ioredis 并创建了以下功能,您能否告诉我对于大型项目是以下最有效的方法:
//key example "prefix*"
function getKeysByPattern(key) {
return new Promise((resolve, reject) => {
var stream = redis.scanStream({
// only returns keys following the pattern of "key"
match: key,
// returns approximately 100 elements per call
count: 100
});
var keys = [];
stream.on('data', function (resultKeys) {
// `resultKeys` is an array of strings representing key names
for (var i = 0; i < resultKeys.length; i++) {
keys.push(resultKeys[i]);
}
});
stream.on('end', function () {
resolve(keys)
});
})
}
//key example "prefix*"
function deleteKeysByPattern(key) {
var stream = redis.scanStream({
// only returns keys following the pattern of "key"
match: key,
// returns approximately 100 elements per call
count: 100
});
var keys = [];
stream.on('data', function (resultKeys) {
// `resultKeys` is an array of strings representing key names
for (var i = 0; i < resultKeys.length; i++) {
keys.push(resultKeys[i]);
}
});
stream.on('end', function () {
redis.unlink(keys)
});
}
@MohammedAl-Mahdawi 对我来说看起来不错。 唯一可能的问题是您将一次将所有匹配的键加载到内存中。 如果这是一个问题,您可以在它们进来后立即分批删除它们:
stream.on('data', function (resultKeys) {
if (resultKeys.length) {
redis.unlink(resultKeys);
}
});
@dirkbonhomme和 @MohammedAl-Mahdawi 这种方法具有原子性问题,可能会在生产中咬你。
@stockholmux感谢您的帮助,请问这个问题的正确解决方案是什么?
对于寻找我们迄今为止所达到的最终结果并相信这是最有效方法的任何人来说,如下所示:
//key example "prefix*"
function getKeysByPattern(key) {
return new Promise((resolve, reject) => {
var stream = redis.scanStream({
// only returns keys following the pattern of "key"
match: key,
// returns approximately 100 elements per call
count: 100
});
var keys = [];
stream.on('data', function (resultKeys) {
// `resultKeys` is an array of strings representing key names
for (var i = 0; i < resultKeys.length; i++) {
keys.push(resultKeys[i]);
}
});
stream.on('end', function () {
resolve(keys)
});
})
}
//key example "prefix*"
function deleteKeysByPattern(key) {
var stream = redis.scanStream({
// only returns keys following the pattern of "key"
match: key,
// returns approximately 100 elements per call
count: 100
});
var keys = [];
stream.on('data', function (resultKeys) {
// `resultKeys` is an array of strings representing key names
for (var i = 0; i < resultKeys.length; i++) {
keys.push(resultKeys[i]);
}
});
stream.on('end', function () {
redis.unlink(keys)
});
}
//key example "prefix*"
function batchDeletionKeysByPattern(key) {
var stream = redis.scanStream({
// only returns keys following the pattern of "key"
match: key,
// returns approximately 100 elements per call
count: 100
});
stream.on('data', function (resultKeys) {
if (resultKeys.length) {
redis.unlink(resultKeys);
}
});
}
上面的代码适用于ioredis 。
请如果您知道更好的方法,请不要犹豫,分享。
@MohammedAl-Mahdawi,
我收到此错误的任何想法
代码库:
let redisDel = () => {
var key="employees*"
return new Promise((resolve, reject) => {
var stream = redis.scanStream({
// only returns keys following the pattern of "key"
match: key,
// returns approximately 100 elements per call
count: 100
});
stream.on('data', function (resultKeys) {
if (resultKeys.length) {
console.log(resultKeys)
redis.unlink(resultKeys);
}
});
stream.on('end', function (resultKeys) {
resolve()
})
})
}
有人在这里给出完美的解决方案吗?
@siddhkadam1881 unlink 命令仅从 Redis 4 开始可用https://redis.io/commands/unlink
您可能正在运行旧版本。 改为尝试del
。
我想了解扫描是如何完成的? 我认为在@MohammedAl-Mahdawi 的解决方案中,如果删除是批量进行的,那么在那个时候添加的我们不想删除的新密钥是否有可能被扫描和删除。 一个lua脚本怎么样?
任何人都知道为什么这个解决方案不能在一个非常简单的 1 个实例 ElastiCache 服务器上工作,但在本地工作? 我可以正常清除键,但是如果我尝试使用流实现,它就永远不会在 ElastiCache 上返回任何键。
最有用的评论
对于寻找我们迄今为止所达到的最终结果并相信这是最有效方法的任何人来说,如下所示:
上面的代码适用于ioredis 。
请如果您知道更好的方法,请不要犹豫,分享。