Node-redis: Effiziente Möglichkeit, Schlüssel nach Muster zu löschen

Erstellt am 5. März 2018  ·  12Kommentare  ·  Quelle: NodeRedis/node-redis

Ich arbeite an einem großen Projekt und an einigen Stellen muss ich Schlüssel nach einem Muster löschen, zum Beispiel möchte ich alle Schlüssel löschen, die mit filterProducts

Ich habe eine Google-Suche durchgeführt und einige Methoden dazu gefunden, wie zum Beispiel die Methode in diesem Artikel

Aber ich weiß nicht, was für ein großes Projekt das effizienteste ist, könnten Sie mir bitte helfen?

  • Version : 2.8.0
  • Plattform : Linux Mint 18.2 (Erstellt auf Ubuntu 16.04)

Hilfreichster Kommentar

Für alle, die nach dem Endergebnis suchen, das wir bisher erreicht haben, und dies für den effizientesten Weg halten, ist Folgendes:

//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);
        }
    });
}

Der obige Code ist für ioredis .
Bitte, wenn Sie jemand sind, der einen besseren Weg kennt, zögern Sie bitte nicht, ihn zu teilen.

Alle 12 Kommentare

Die Methode, die Sie verlinkt haben, ist eine ziemlich schreckliche Vorgehensweise. KEYS ist ein No-Go für die Produktion und DEL ist auch ziemlich ineffizient. Ich würde mit SCAN und UNLINK einchecken. Auf diese Weise können Sie eine Handvoll Schlüssel gleichzeitig löschen, ohne Redis zu binden.

Abgesehen davon liegt diese Art von Skript bei Ihnen und übersteigt den Umfang der Clientbibliothek. Ich werde das Thema schließen.

@MohammedAl-Mahdawi Ich habe einen ähnlichen Anwendungsfall in einem meiner Projekte und verwende die scanStream Implementierung von ioredis. Dies ist im Grunde eine einfachere Möglichkeit, den Befehl scan : https://github.com/luin/ioredis#streamify -scanning

Wenn Sie SCAN und UNLINK wie bereits @stockholmux erwähnt, sollten Sie in der Lage sein, beliebig viele Schlüssel zu entfernen, ohne Redis zu blockieren.

@dirkbonhomme Vielen Dank für deine Hilfe, das weiß ich sehr zu schätzen.

Ich bin Ihrem Rat gefolgt und habe ioredis verwendet und die folgenden Funktionen erstellt. Können Sie mir bitte sagen, ob für große Projekte der folgende Weg am effizientesten ist oder nicht:

//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 sieht für mich gut aus. Das einzige mögliche Problem besteht darin, dass Sie alle übereinstimmenden Schlüssel gleichzeitig in den Speicher laden. Wenn dies ein Problem darstellt, können Sie sie stapelweise entfernen, sobald sie eingehen:

stream.on('data', function (resultKeys) {
        if (resultKeys.length) {
              redis.unlink(resultKeys);
        }
    });

@dirkbonhomme und @MohammedAl-Mahdawi Diese Methode weist Atomaritätsprobleme auf, die Sie in der Produktion beißen könnten.

@stockholmux Vielen Dank für Ihre Hilfe, also was ist bitte die richtige Lösung für dieses Problem?

Für alle, die nach dem Endergebnis suchen, das wir bisher erreicht haben, und dies für den effizientesten Weg halten, ist Folgendes:

//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);
        }
    });
}

Der obige Code ist für ioredis .
Bitte, wenn Sie jemand sind, der einen besseren Weg kennt, zögern Sie bitte nicht, ihn zu teilen.

@MohammedAl-Mahdawi ,
Ich bekomme diesen Fehler alle Ideen dazu
Codebasis:

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

Gibt hier jemand eine perfekte Lösung?

@siddhkadam1881 Der https://redis.io/commands/unlink
Sie verwenden wahrscheinlich eine ältere Version. Versuchen Sie es stattdessen mit del .

Ich möchte verstehen, wie das Scannen erfolgt?. Ich denke, in der Lösung von @MohammedAl-Mahdawi, wenn das Löschen in Stapeln erfolgt, besteht die Möglichkeit, dass in dieser Zeit hinzugefügte neue Schlüssel, die wir nicht löschen möchten, gescannt und gelöscht werden. Wie wäre es mit einem Lua-Skript?

Hat jemand eine Idee, warum diese Lösung auf einem sehr einfachen 1-Instanz-ElastiCache-Server nicht funktionieren würde, aber lokal funktioniert? Ich kann Schlüssel normal löschen, aber wenn ich versuche, die Stream-Implementierung zu verwenden, gibt sie einfach keine Schlüssel auf ElastiCache zurück.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

shmendo picture shmendo  ·  6Kommentare

ghost picture ghost  ·  3Kommentare

id0Sch picture id0Sch  ·  4Kommentare

strumwolf picture strumwolf  ·  4Kommentare

abhaygarg picture abhaygarg  ·  5Kommentare