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私のプロジェクトの1つで同様のユースケースがあり、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コマンドは、 ますhttps://redis.io/commands/unlink
おそらく古いバージョンを実行しています。 代わりにdel試してください。

スキャンがどのように行われるのか理解したいですか? @ MohammedAl-Mahdawiによるソリューションでは、削除がバッチで発生した場合、その間に追加された、削除したくない新しいキーがスキャンされて削除される可能性があると思います。 luaスクリプトはどうですか?

このソリューションが非常に単純な1インスタンスのElastiCacheサーバーでは機能しないが、ローカルでは機能する理由は誰にもわかりません。 通常どおりキーをクリアできますが、ストリーム実装を使用しようとすると、ElastiCacheでキーが返されることはありません。

このページは役に立ちましたか?
0 / 5 - 0 評価