Node-redis: 按模式删除键的有效方法

创建于 2018-03-05  ·  12评论  ·  资料来源: NodeRedis/node-redis

我正在做一个大项目,在某些地方,我必须按模式删除键,例如,我想删除所有以filterProducts开头的键

我进行了谷歌搜索并找到了一些方法,例如,本文中的方法

但是我不知道对于一个大项目来说什么是有效的,你能帮我吗?

  • 版本:2.8.0
  • 平台:Linux Mint 18.2(基于 Ubuntu 16.04)

最有用的评论

对于寻找我们迄今为止所达到的最终结果并相信这是最有效方法的任何人来说,如下所示:

//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
请如果您知道更好的方法,请不要犹豫,分享。

所有12条评论

您链接到的方法是一种非常糟糕的处理方式。 KEYS不适合生产,DEL 也非常低效。 我会检查使用SCANUNLINK 。 通过这种方式,您可以一次删除少量键而不会占用 Redis。

话虽如此,这种类型的脚本取决于您,超出了客户端库的范围。 我要结束这个问题。

@MohammedAl-Mahdawi 我在我的一个项目中有一个类似的用例,并使用 ioredis 提供的scanStream实现。 这基本上是使用scan命令的更简单方法: https :

如果您像前面提到的@stockholmux一样使用SCANUNLINK ,您应该能够在不阻塞 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()
        })

    })
}

screenshot from 2019-03-05 19 28 10

有人在这里给出完美的解决方案吗?

@siddhkadam1881 unlink 命令仅从 Redis 4 开始可用https://redis.io/commands/unlink
您可能正在运行旧版本。 改为尝试del

我想了解扫描是如何完成的? 我认为在@MohammedAl-Mahdawi 的解决方案中,如果删除是批量进行的,那么在那个时候添加的我们不想删除的新密钥是否有可能被扫描和删除。 一个lua脚本怎么样?

任何人都知道为什么这个解决方案不能在一个非常简单的 1 个实例 ElastiCache 服务器上工作,但在本地工作? 我可以正常清除键,但是如果我尝试使用流实现,它就永远不会在 ElastiCache 上返回任何键。

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

abhaygarg picture abhaygarg  ·  5评论

Mickael-van-der-Beek picture Mickael-van-der-Beek  ·  6评论

yuany picture yuany  ·  4评论

michaelwittig picture michaelwittig  ·  3评论

gpascale picture gpascale  ·  4评论