exist - redis python example
Redis Python: cómo eliminar todas las claves según un patrón específico En Python, sin iteración de Python (9)
Aquí hay un ejemplo completo de trabajo usando py-redis :
from redis import StrictRedis
cache = StrictRedis()
def clear_ns(ns):
"""
Clears a namespace
:param ns: str, namespace i.e your:prefix
:return: int, cleared keys
"""
count = 0
ns_keys = ns + ''*''
for key in cache.scan_iter(ns_keys):
cache.delete(key)
count += 1
return count
También puede hacer scan_iter
para obtener todas las claves en la memoria, y luego pasar todas las claves para delete
para una eliminación masiva, pero puede tomar una buena parte de la memoria para espacios de nombres más grandes. Así que probablemente lo mejor es ejecutar una delete
para cada clave.
¡Aclamaciones!
ACTUALIZAR:
Desde que escribí la respuesta, comencé a usar la función de canalización de redis para enviar todos los comandos en una solicitud y evitar la latencia de la red:
from redis import StrictRedis
cache = StrictRedis()
def clear_cache_ns(ns):
"""
Clears a namespace in redis cache.
This may be very time consuming.
:param ns: str, namespace i.e your:prefix*
:return: int, num cleared keys
"""
count = 0
pipe = cache.pipeline()
for key in cache.scan_iter(ns_keys):
pipe.delete(key)
count += 1
pipe.execute()
return count
ACTUALIZACIÓN2 (Mejor desempeño):
Si usa scan
lugar de scan_iter
, puede controlar el tamaño del fragmento y recorrer el cursor utilizando su propia lógica. Esto también parece ser mucho más rápido, especialmente cuando se trata de muchas claves. Si agrega la canalización a esto, obtendrá un poco de aumento de rendimiento, 10-25% según el tamaño del fragmento, al costo del uso de la memoria, ya que no enviará el comando de ejecución a Redis hasta que se genere todo. Así que me quedé con la exploración:
from redis import StrictRedis
cache = StrictRedis()
CHUNK_SIZE = 5000
def clear_ns(ns):
"""
Clears a namespace
:param ns: str, namespace i.e your:prefix
:return: int, cleared keys
"""
cursor = ''0''
ns_keys = ns + ''*''
while cursor != 0::
cursor, keys = cache.scan(cursor=cursor, match=ns_keys, count=CHUNK_SIZE)
if keys:
cache.delete(*keys)
return True
Aquí hay algunos puntos de referencia:
5k trozos usando un grupo ocupado de Redis: Done removing using scan in 4.49929285049 Done removing using scan_iter in 98.4856731892 Done removing using scan_iter & pipe in 66.8833789825 Done removing using scan & pipe in 3.20298910141
5k trozos y una pequeña red de desarrollo inactivo (localhost): Done removing using scan in 1.26654982567 Done removing using scan_iter in 13.5976779461 Done removing using scan_iter & pipe in 4.66061878204 Done removing using scan & pipe in 1.13942599297
Estoy escribiendo un comando de administración de django para manejar parte de nuestro almacenamiento en caché de redis. Básicamente, debo elegir todas las teclas, que confirman un determinado patrón (por ejemplo: "prefijo: *") y eliminarlas.
Sé que puedo usar el cli para hacer eso:
redis-cli KEYS "prefix:*" | xargs redis-cli DEL
Pero necesito hacer esto desde dentro de la aplicación. Así que necesito usar el enlace de python (estoy usando py-redis). He intentado introducir una lista en eliminar, pero falla:
from common.redis_client import get_redis_client
cache = get_redis_client()
x = cache.keys(''prefix:*'')
x == [''prefix:key1'',''prefix:key2''] # True
# Y ahora
cache.delete(x)
# devuelve 0. no se elimina nada
Sé que puedo iterar sobre x:
for key in x:
cache.delete(key)
Pero eso sería perder la velocidad increíble y el mal uso de sus capacidades. ¿Hay una solución pitónica con py-redis, sin iteración y / o el cli?
¡Gracias!
De la Documentation
delete(*names) Delete one or more keys specified by names
Esto solo quiere que se elimine un argumento por clave y luego le dirá cuántos de ellos se encontraron y eliminaron.
En el caso de su código anterior, creo que solo puede hacer:
redis.delete(*x)
Pero debo admitir que soy nuevo en Python y acabo de hacer:
deleted_count = redis.delete(''key1'', ''key2'')
Por cierto, para el django-redis puede usar lo siguiente (de https://niwinz.github.io/django-redis/latest/ ):
from django.core.cache import cache
cache.delete_pattern("foo_*")
Puede usar un patrón específico para hacer coincidir todas las teclas y eliminarlas:
import redis
client = redis.Redis(host=''192.168.1.106'', port=6379,
password=''pass'', decode_responses=True)
for key in client.keys(''prefix:*''):
client.delete(key)
Según mi prueba, costará demasiado tiempo si uso la solución scan_iter
(como escribió Alex Toderita ).
Por lo tanto, prefiero usar:
from redis.connection import ResponseError
try:
redis_obj.eval(''''''return redis.call(''del'', unpack(redis.call(''keys'', ARGV[1])))'''''', 0, ''prefix:*'')
except ResponseError:
pass
El prefix:*
es el patrón.
se refiere a: https://.com/a/16974060
Use los iteradores SCAN: https://pypi.python.org/pypi/redis
for key in r.scan_iter("prefix:*"):
r.delete(key)
Utilice delete_pattern: https://niwinz.github.io/django-redis/latest/
from django.core.cache import cache
cache.delete_pattern("prefix:*")
creo que el
for key in x: cache.delete(key)
Es bastante bueno y conciso. delete
realmente quiere una tecla a la vez, así que tienes que hacer un bucle.
De lo contrario, esta pregunta y respuesta anteriores lo llevarán a una solución basada en lua.
cache.delete(*keys)
de Dirk funciona bien, pero asegúrese de que las claves no redis.exceptions.ResponseError: wrong number of arguments for ''del'' command
vacías para evitar un redis.exceptions.ResponseError: wrong number of arguments for ''del'' command
.
Si está seguro de que siempre obtendrá un resultado: cache.delete(*cache.keys(''prefix:*'') )