Es gibt einen Beitrag über einen Redis-Befehl, um alle verfügbaren Schlüssel abzurufen, aber ich würde es gerne mit Python tun.
Wie kann man das machen?
Antworten:
Verwenden scan_iter()
scan_iter()
ist keys()
für eine große Anzahl von Schlüsseln überlegen, da Sie einen Iterator erhalten, den Sie verwenden können, anstatt zu versuchen, alle Schlüssel in den Speicher zu laden.
Ich hatte 1B-Datensätze in meinem Redis und konnte nie genug Speicher bekommen, um alle Schlüssel auf einmal zurückzugeben.
SCANNING KEYS ONE-BY-ONE
Hier ist ein Python-Snippet, mit scan_iter()
dem alle Schlüssel, die einem Muster entsprechen, aus dem Store abgerufen und einzeln gelöscht werden:
import redis
r = redis.StrictRedis(host='localhost', port=6379, db=0)
for key in r.scan_iter("user:*"):
# delete the key
r.delete(key)
SCANNEN IN BATCHES
Wenn Sie eine sehr große Liste von Schlüsseln zum Scannen haben, z. B. mehr als 100.000 Schlüssel, ist es effizienter, sie in Stapeln wie folgt zu scannen:
import redis
from itertools import izip_longest
r = redis.StrictRedis(host='localhost', port=6379, db=0)
# iterate a list in batches of size n
def batcher(iterable, n):
args = [iter(iterable)] * n
return izip_longest(*args)
# in batches of 500 delete keys matching user:*
for keybatch in batcher(r.scan_iter('user:*'),500):
r.delete(*keybatch)
Ich habe dieses Skript verglichen und festgestellt, dass die Verwendung einer Stapelgröße von 500 fünfmal schneller war als das Scannen von Schlüsseln nacheinander. Ich habe verschiedene Chargengrößen (3,50,500,1000,5000) getestet und festgestellt, dass eine Chargengröße von 500 optimal zu sein scheint.
Beachten Sie, ob Sie das scan_iter()
oder verwendenkeys()
, dass die Operation Methode verwenden, nicht atomar ist und teilweise fehlschlagen kann.
Vermeiden Sie definitiv die Verwendung von XARGS in der Befehlszeile
Ich empfehle dieses Beispiel nicht, das ich an anderer Stelle wiederholt gefunden habe. Es schlägt bei Unicode-Schlüsseln fehl und ist selbst bei einer moderaten Anzahl von Schlüsseln unglaublich langsam:
redis-cli --raw keys "user:*"| xargs redis-cli del
In diesem Beispiel erstellt xargs für jeden Schlüssel einen neuen Redis-Cli-Prozess! das ist schlecht.
Ich habe diesen Ansatz als 4-mal langsamer als das erste Python-Beispiel bewertet, bei dem jeder Schlüssel einzeln und 20-mal langsamer gelöscht wurde als beim Löschen in Stapeln von 500.
Ja, verwenden Sie keys()
aus dem StrictRedis-Modul:
>>> import redis
>>> r = redis.StrictRedis(host=YOUR_HOST, port=YOUR_PORT, db=YOUR_DB)
>>> r.keys()
Wenn Sie ein Nullmuster angeben, werden alle abgerufen. Gemäß der verlinkten Seite:
Tasten (Muster = '*')
Gibt eine Liste der Schlüssel zurück, die dem Muster entsprechen
SCAN
Befehl, da dies jetzt eine bevorzugte Methode ist, um alle Schlüssel mit der O (1) -Zeitkomplexität jeder Anforderung abzurufen. (und O (N) für alle Anfragen)
r.keys()
ist ziemlich langsam, wenn Sie versuchen, ein Muster abzugleichen und nicht nur alle Schlüssel zurückzugeben. scan
import redis
r = redis.Redis("localhost", 6379)
for key in r.scan_iter():
print key
mit Pyredis Bibliothek
Verfügbar seit 2.8.0.
Zeitliche Komplexität: O (1) für jeden Anruf. O (N) für eine vollständige Iteration, einschließlich genügend Befehlsaufrufe, damit der Cursor auf 0 zurückkehrt. N ist die Anzahl der Elemente in der Sammlung.
Ich möchte einen Beispielcode hinzufügen, der zu Patricks Antwort und anderen passt.
Dies zeigt die Ergebnisse sowohl mit Schlüsseln als auch mit der scan_iter-Technik. Beachten Sie außerdem, dass Python3 zip_longest anstelle von izip_longest verwendet. Der folgende Code durchläuft alle Schlüssel und zeigt sie an. Ich habe die Stapelgröße als Variable auf 12 gesetzt, um die Ausgabe zu verkleinern.
Ich habe dies geschrieben, um besser zu verstehen, wie das Stapeln von Schlüsseln funktioniert.
import redis
from itertools import zip_longest
\# connection/building of my redisObj omitted here
\# iterate a list in batches of size n
def batcher(iterable, n):
args = [iter(iterable)] * n
return zip_longest(*args)
result1 = redisObj.get("TestEN")
print(result1)
result2 = redisObj.get("TestES")
print(result2)
print("\n\nLoop through all keys:")
keys = redisObj.keys('*')
counter = 0
print("len(keys)=", len(keys))
for key in keys:
counter +=1
print (counter, "key=" +key, " value=" + redisObj.get(key))
print("\n\nLoop through all keys in batches (using itertools)")
\# in batches of 500 delete keys matching user:*
counter = 0
batch_counter = 0
print("Try scan_iter:")
for keybatch in batcher(redisObj.scan_iter('*'), 12):
batch_counter +=1
print(batch_counter, "keybatch=", keybatch)
for key in keybatch:
if key != None:
counter += 1
print(" ", counter, "key=" + key, " value=" + redisObj.get(key))
Beispielausgabe:
Loop through all keys:
len(keys)= 2
1 key=TestES value=Ola Mundo
2 key=TestEN value=Hello World
Loop through all keys in batches (using itertools)
Try scan_iter:
1 keybatch= ('TestES', 'TestEN', None, None, None, None, None, None, None, None, None, None)
1 key=TestES value=Ola Mundo
2 key=TestEN value=Hello World
Beachten Sie, dass Redis-Befehle Single-Threaded sind. Wenn Sie also eine Taste () ausführen, können Sie andere Redis-Aktivitäten blockieren. Sehen Sie hier einen ausgezeichneten Beitrag, der dies ausführlicher erklärt: SCAN vs KEYS-Leistung in Redis