Frage

In meiner Redis DB habe ich eine Reihe von prefix:<numeric_id> Hashes.

Manchmal möchte ich sie alle atomar spülen. Wie kann ich dies tun, ohne etwas verteilte Verriegelungsmechanismus mit?

War es hilfreich?

Lösung

Beginnend mit redis 2.6.0 können Sie Lua-Skripte ausführen, die atomar ausgeführt werden. Ich habe noch nie eine geschrieben, aber ich denke, es ist so etwas wie dies aussehen würde

EVAL "return redis.call('del', unpack(redis.call('keys', ARGV[1])))" 0 prefix:[YOUR_PREFIX e.g delete_me_*]

Sehen Sie die EVAL Dokumentation .

Andere Tipps

in bash ausführen:

redis-cli KEYS "prefix:*" | xargs redis-cli DEL

UPDATE

Ok, ich verstand. Was ist mit dieser Art und Weise: store aktuelle zusätzliche inkrementelle Präfix und fügen Sie alle Ihre Schlüssel. Zum Beispiel:

Sie haben Werte wie folgt aus:

prefix_prefix_actuall = 2
prefix:2:1 = 4
prefix:2:2 = 10

Wenn Sie zum Entfernen der Daten benötigen, können Sie prefix_actuall zuerst ändern (zB Set prefix_prefix_actuall = 3), so dass Ihre Anwendung neue Daten auf Tasten schreibt, wird das Präfix: 3: 1 und prefix: 3: 2. Dann können Sie sicher alte Werte von Präfix nehmen: 2: 1 und prefix: 2:. 2 und löschen alte Tasten

Hier ist eine vollständig funktioniert und Atom-Version von einer Wildcard in Lua implementiert löschen. Es wird viel schneller als die xargs Version wegen viel weniger Netzwerk zurück und nach vorne laufen, und es ist völlig atomar, alle anderen Anträge gegen redis blockiert, bis es fertig ist. Wenn Sie auf atomar Löschtasten auf Redis 2.6.0 oder höher wollen, dann ist dies definitiv der Weg zu gehen:

redis-cli -n [some_db] -h [some_host_name] EVAL "return redis.call('DEL', unpack(redis.call('KEYS', ARGV[1] .. '*')))" 0 prefix:

Dies ist eine Arbeitsversion der Idee @ mcdizzle in seiner Antwort auf diese Frage. Kredit für die Idee, 100% geht zu ihm.

EDIT: Per Kikito Kommentar unten, wenn Sie mehr Tasten haben in Ihrem Redis Server als freier Speicher zu löschen, werden Sie die "zu viele Elemente" Fehler entpacken. In diesem Fall tun:

for _,k in ipairs(redis.call('keys', ARGV[1])) do 
    redis.call('del', k) 
end

Wie Kikito vorgeschlagen.

Disclaimer:. Die folgende Lösung nicht bietet Unteilbarkeit

Beginnend mit v2.8 Sie wirklich will Befehl das SCAN verwenden anstelle von KEYS [1 ]. Der folgende Bash-Skript zeigt Löschen von Schlüsseln durch Muster:

#!/bin/bash

if [ $# -ne 3 ] 
then
  echo "Delete keys from Redis matching a pattern using SCAN & DEL"
  echo "Usage: $0 <host> <port> <pattern>"
  exit 1
fi

cursor=-1
keys=""

while [ $cursor -ne 0 ]; do
  if [ $cursor -eq -1 ]
  then
    cursor=0
  fi

  reply=`redis-cli -h $1 -p $2 SCAN $cursor MATCH $3`
  cursor=`expr "$reply" : '\([0-9]*[0-9 ]\)'`
  keys=${reply##[0-9]*[0-9 ]}
  redis-cli -h $1 -p $2 DEL $keys
done

[1] KEYS ein gefährlicher Befehl ist, die möglicherweise in einem DoS führen kann. Im Folgenden ist ein Zitat aus seiner Dokumentation Seite:

  

Achtung: betrachtet KEYS als Befehl, der nur in Produktionsumgebungen mit äußerster Vorsicht verwendet werden soll. Es kann die Leistung ruinieren, wenn es gegen die großen Datenbanken ausgeführt wird. Dieser Befehl wird für die Fehlersuche und speziellen Operationen bestimmt, wie Ihr Layout Schlüsselraum zu ändern. Verwenden Sie keine Schlüssel in Ihrem normalen Anwendungscode. Wenn Sie nach einer Möglichkeit, Schlüssel in einer Teilmenge der Schlüsselraum zu finden, sollten Sie Sätze verwenden.

UPDATE: ein Motto für den gleichen grundlegenden Effekt -

$ redis-cli --scan --pattern "*:foo:bar:*" | xargs -L 100 redis-cli DEL

Für diejenigen, die Schwierigkeiten Parsen andere Antworten wurden mit:

eval "for _,k in ipairs(redis.call('keys','key:*:pattern')) do redis.call('del',k) end" 0

Ersetzen key:*:pattern mit Ihrem eigenen Muster und geben Sie diese in redis-cli und Sie sind gut zu gehen.

Kredit LISCO von: http://redis.io/commands/del

Ich verwende unter Befehl in redis 3.2.8

redis-cli KEYS *YOUR_KEY_PREFIX* | xargs redis-cli DEL

Sie können mehr Hilfe bekommen, um Schlüssel Mustersuche im Zusammenhang von hier: - https://redis.io/commands/ Tasten . Verwenden Sie Ihre bequeme glob-style-Muster wie pro Ihre Anforderung wie *YOUR_KEY_PREFIX* oder YOUR_KEY_PREFIX?? oder andere.

Und wenn einer von euch integriert hat Redis PHP-Bibliothek als unten Funktion werden Ihnen helfen.

flushRedisMultipleHashKeyUsingPattern("*YOUR_KEY_PATTERN*"); //function call

function flushRedisMultipleHashKeyUsingPattern($pattern='')
        {
            if($pattern==''){
                return true;
            }

            $redisObj = $this->redis;
            $getHashes = $redisObj->keys($pattern);
            if(!empty($getHashes)){
                $response = call_user_func_array(array(&$redisObj, 'del'), $getHashes); //setting all keys as parameter of "del" function. Using this we can achieve $redisObj->del("key1","key2);
            }
        }

Danke:)

@ mcdizle-Lösung funktioniert nicht nur für einen Eintrag funktioniert.

Dies funktioniert für alle Tasten mit demselben Präfix

EVAL "for i, name in ipairs(redis.call('KEYS', ARGV[1])) do redis.call('DEL', name); end" 0 prefix*

Hinweis: Sie sollten ersetzen 'prefix' mit Schlüsselpräfix ...

Sie können diesen Befehl auch verwenden, um die Schlüssel zu löschen: -

Angenommen, es gibt viele Arten von Schlüsseln in Ihrem redis wie -

  1. 'xyz_category_fpc_12'
  2. 'xyz_category_fpc_245'
  3. 'xyz_category_fpc_321'
  4. 'xyz_product_fpc_876'
  5. 'xyz_product_fpc_302'
  6. 'xyz_product_fpc_01232'

Ex- ' xyz_category_fpc ' hier xyz ist ein Site-Name , und diese Tasten beziehen sich auf Produkte und Kategorien einer E-Commerce-Site und erzeugt durch FPC.

Wenn Sie diesen Befehl wie unten -

redis-cli --scan --pattern 'key*' | xargs redis-cli del

oder

redis-cli --scan --pattern 'xyz_category_fpc*' | xargs redis-cli del

Es löscht alle Tasten wie ' xyz_category_fpc ' (löschen 1, 2 und 3 Tasten). Für löschen andere 4, 5 und 6 Zifferntasten ' xyz_product_fpc ' in obigem Befehl.

Wenn Sie auf Löschen Alles in Redis , dann folgen diese Befehle -

Mit redis-cli:

  1. FLUSHDB -. Entfernt Daten aus Ihrer Verbindung der aktuellen Datenbank
  2. flushall -. Entfernt Daten aus allen Datenbanken

Beispiel: - in der Shell:

redis-cli flushall
redis-cli flushdb

Wenn Sie Leerzeichen im Namen der Tasten haben, können Sie dies in der Bash verwenden:

redis-cli keys "pattern: *" | xargs -L1 -I '$' echo '"$"' | xargs redis-cli del

@ itamar Antwort ist groß, aber die Analyse der Antwort wurde nicht für mich arbeiten, esp. in dem Fall, in dem es keine Tasten in einem bestimmten Scan gefunden. Eine eventuell einfachere Lösung, direkt von der Konsole aus:

redis-cli -h HOST -p PORT  --scan --pattern "prefix:*" | xargs -n 100 redis-cli DEL

Dies nutzt auch SCAN, die Schlüssel in der Produktion vorzuziehen ist, ist aber nicht atomar.

ich das gleiche Problem nur hatte. Ich Sitzungsdaten für einen Benutzer in dem Format gespeichert:

session:sessionid:key-x - value of x
session:sessionid:key-y - value of y
session:sessionid:key-z - value of z

So war jeder Eintrag ein eigenes Schlüssel-Wert-Paar. Wenn die Sitzung zerstört wird, wollte ich alle Sitzungsdaten entfernen, indem Tasten mit dem Muster session:sessionid:* Löschen -. Aber Redis nicht eine solche Funktion hat

Was ich getan habe: speichern die Sitzungsdaten innerhalb eines Hash . Ich schaffe nur einen Hash mit dem Hash-ID von session:sessionid und dann schiebe ich key-x, key-y, key-z in diesem Hash (um mich nicht Sache tat), und wenn ich nicht brauchen, dass Hash mehr ich nur ein DEL session:sessionid und alle Daten im Zusammenhang mit, dass Hash-id ist weg. DEL ist atomar und den Zugriff auf Daten / Schreiben von Daten an die Hash-O (1).

Zu Ihrer Information.

  • nur mit bash und redis-cli
  • nicht keys mit (diese Anwendungen scan)
  • funktioniert gut in Cluster-Modus
  • nicht atomar

Vielleicht brauchen Sie nur Großbuchstaben zu ändern.

scan-match.sh

#!/bin/bash
rcli=“/YOUR_PATH/redis-cli" 
default_server="YOUR_SERVER"
default_port="YOUR_PORT"
servers=`$rcli -h $default_server -p $default_port cluster nodes | grep master | awk '{print $2}' | sed 's/:.*//'`
if [ x"$1" == "x" ]; then 
    startswith="DEFAULT_PATTERN"
else
    startswith="$1"
fi
MAX_BUFFER_SIZE=1000
for server in $servers; do 
    cursor=0
    while 
        r=`$rcli -h $server -p $default_port scan $cursor match "$startswith*" count $MAX_BUFFER_SIZE `
        cursor=`echo $r | cut -f 1 -d' '`
        nf=`echo $r | awk '{print NF}'`
        if [ $nf -gt 1 ]; then
            for x in `echo $r | cut -f 1 -d' ' --complement`; do 
                echo $x
            done
        fi
        (( cursor != 0 ))
    do
        :
    done
done

clear-redis-key.sh

#!/bin/bash
STARTSWITH="$1"

RCLI=YOUR_PATH/redis-cli
HOST=YOUR_HOST
PORT=6379
RCMD="$RCLI -h $HOST -p $PORT -c "

./scan-match.sh $STARTSWITH | while read -r KEY ; do
    $RCMD del $KEY 
done

Ausführen bei Bash-Eingabeaufforderung

$ ./clear-redis-key.sh key_head_pattern

Ich denke, was könnte Ihnen helfen, ist die MULTI / EXEC / Aussonderungs . Während nicht 100% Äquivalent von Transaktionen Sie sollte die Löschungen von anderen Updates isolieren kann.

Es ist einfach über "Remove Zweig" -Funktionalität in FastoRedis implementiert ist, wählen Sie einfach Zweig, die Sie entfernen möchten.

Bitte diesen Befehl verwenden und versuchen:

redis-cli --raw keys "$PATTERN" | xargs redis-cli del

Eine Version mit SCAN statt KEYS (wie für Produktionsserver empfohlen) und --pipe statt xargs.

Ich ziehe Rohr über xargs, weil es effizienter ist und funktioniert, wenn Ihre Schlüssel Anführungszeichen oder andere Sonderzeichen enthalten, dass die Shell mit Versuch und interpretieren. Die Regex-Substitution in diesem Beispiel wickelt den Schlüssel in doppelten Anführungszeichen, und entkommt keine doppelten Anführungszeichen innen.

export REDIS_HOST=your.hostname.com
redis-cli -h "$REDIS_HOST" --scan --pattern "YourPattern*" > /tmp/keys
time cat /tmp/keys | perl -pe 's/"/\\"/g;s/^/DEL "/;s/$/"/;'  | redis-cli -h "$REDIS_HOST" --pipe

Dies ist keine direkte Antwort auf die Frage, aber da ich hier bin, wenn meine eigenen Antworten suchen, werde ich dies hier teilen hier.

Wenn Sie Dutzende oder Hunderte von Millionen von Schlüsseln haben Sie passen müssen, die hier angegebenen Antworten Redis verursachen nicht ansprechbar für erhebliche Menge an Zeit zu sein (Minuten?), Und möglicherweise zum Absturz wegen Speicherverbrauch (sicher sein, Hintergrund speichert in in der Mitte der Operation treten wird).

Der folgende Ansatz ist unbestreitbar hässlich, aber ich habe keine besseren finden. Atomicity ist hier nicht in Frage, in diesem Fall Hauptziel ist es Redis zu halten und reaktions 100% der Zeit. Es wird perfekt funktionieren, wenn Sie alle Ihre Schlüssel haben in einer der Datenbanken und Sie keine Muster passen müssen, kann aber nicht verwenden http://redis.io/commands/FLUSHDB , weil es die Natur ist blockiert.

Idee ist einfach: ein Skript schreiben, das läuft in einer Schleife und Verwendungen O (1) Betrieb wie http: // redis.io/commands/SCAN oder http://redis.io/commands/RANDOMKEY Schlüssel zu erhalten, überprüft, ob sie mit dem Muster übereinstimmen (wenn Sie es brauchen) und http://redis.io/commands/ DEL sie eins nach dem anderen.

Wenn es ein besserer Weg, es zu tun, lass es mich wissen, ich werde die Antwort aktualisieren.

Beispiel-Implementierung mit randomkey in Ruby als Rake Aufgabe, ein nicht blockierende Ersatz von so etwas wie redis-cli -n 3 flushdb:

desc 'Cleanup redis'
task cleanup_redis: :environment do
  redis = Redis.new(...) # connection to target database number which needs to be wiped out
  counter = 0
  while key = redis.randomkey               
    puts "Deleting #{counter}: #{key}"
    redis.del(key)
    counter += 1
  end
end

ich die meisten Methoden ausprobiert oben erwähnt, aber sie haben für mich keine Arbeit, nach einigen Suchen fand ich diese Punkte:

  • Wenn Sie mehr als eine db auf redis haben, sollten Sie die Datenbank mit -n [number]
  • bestimmen
  • , wenn Sie ein paar Tasten verwenden del aber wenn es Tausende oder Millionen von Schlüsseln sind, es ist besser zu nutzen unlink weil unlink wird nicht blockierenden , während del blockiert, für weitere Informationen besuchen Sie diese Seite < a href = "https://stackoverflow.com/questions/45818371/is-the-unlink-command-always-better-than-del-command"> unlink vs del
  • auch keys wie del sind und blockiert

so habe ich diesen Code zu löschen Tasten durch Muster:

 redis-cli -n 2 --scan --pattern '[your pattern]' | xargs redis-cli -n 2 unlink 

ich alle Antworten unterstützen in Bezug auf ein Tool mit oder Lua Ausdruck auszuführen.

Eine weitere Option von meiner Seite:

In der Produktion und Pre-Production-Datenbanken gibt es Tausende von Schlüsseln. Von Zeit zu Zeit müssen wir einige Schlüssel löschen (durch eine Maske), modifizieren durch einige Kriterien etc. Natürlich gibt es keine Möglichkeit, es von CLI manuell zu tun, vor allem sharding mit (512 logischem dbs in jedem physischen).

Zu diesem Zweck Ich schreibe Java-Client-Tool, das alle funktionierts. Im Fall der Tasten Löschen kann das Dienstprogramm sehr einfach sein, nur eine Klasse gibt:

public class DataCleaner {

    public static void main(String args[]) {
        String keyPattern = args[0];
        String host = args[1];
        int port = Integer.valueOf(args[2]);
        int dbIndex = Integer.valueOf(args[3]);

        Jedis jedis = new Jedis(host, port);

        int deletedKeysNumber = 0;
        if(dbIndex >= 0){
            deletedKeysNumber += deleteDataFromDB(jedis, keyPattern, dbIndex);
        } else {
            int dbSize = Integer.valueOf(jedis.configGet("databases").get(1));
            for(int i = 0; i < dbSize; i++){
                deletedKeysNumber += deleteDataFromDB(jedis, keyPattern, i);
            }
        }

        if(deletedKeysNumber == 0) {
            System.out.println("There is no keys with key pattern: " + keyPattern + " was found in database with host: " + host);
        }
    }

    private static int deleteDataFromDB(Jedis jedis, String keyPattern, int dbIndex) {
        jedis.select(dbIndex);
        Set<String> keys = jedis.keys(keyPattern);
        for(String key : keys){
            jedis.del(key);
            System.out.println("The key: " + key + " has been deleted from database index: " + dbIndex);
        }

        return keys.size();
    }

}

Im Folgenden Befehl für mich gearbeitet.

redis-cli -h redis_host_url KEYS "*abcd*" | xargs redis-cli -h redis_host_url DEL

Anzeige von jetzt können Sie ein redis-Client verwenden und führen erste SCAN (unterstützt Pattern Matching) und dann DEL jede Taste einzeln.

Es gibt jedoch ein Problem auf offiziell redis GitHub ein Rüttler-Matching-del hier zu erstellen , gehen zeigen es etwas Liebe, wenn Sie es nützlich finden!

Armer Atommassen löschen?

vielleicht könnte man sie setzt alle die gleiche Sekunde EXPIREAT - wie ein paar Minuten in der Zukunft -. Und dann bis zu diesem Zeitpunkt warten und ihnen alle „Selbstzerstörung“ zur gleichen Zeit sehen

, aber ich bin nicht wirklich sicher, wie Atom das wäre.

Frühling RedisTemplate selbst bietet die Funktionalität. RedissonClient in der neuesten Version hat die "deleteByPattern" Funktionalität veraltet.

Set<String> keys = redisTemplate.keys("geotag|*");
redisTemplate.delete(keys);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top