hkeys exist example commands python redis redis-py

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'')



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




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:*'') )