remove pattern keys delete redis

pattern - redis remove list



Cómo eliminar atómicamente las claves que coinciden con un patrón utilizando Redis (20)

En mi base de datos de Redis tengo varios prefix:<numeric_id> hash prefix:<numeric_id> .

A veces quiero purgarlos todos atómicamente. ¿Cómo hago esto sin usar algún mecanismo de bloqueo distribuido?


A partir de redis 2.6.0, puede ejecutar scripts lua, que se ejecutan de forma atómica. Nunca he escrito una, pero creo que se vería así.

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

Consulte la documentación de EVAL .


Acabo de tener el mismo problema. Almacené datos de sesión para un usuario en el formato:

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

Por lo tanto, cada entrada era un par clave-valor separado. Cuando se destruye la sesión, quise eliminar todos los datos de la sesión mediante la eliminación de claves con la session:sessionid:* patrón session:sessionid:* - pero redis no tiene esa función.

Lo que hice: almacenar los datos de la sesión dentro de un hash . Simplemente creo un hash con el id de hash de session:sessionid y luego presiono key-x , key-y , key-z en ese hash (el orden no me importaba) y si ya no necesito ese hash, simplemente lo hago. una DEL session:sessionid y todos los datos asociados con ese hash id se han ido. DEL es atómico y el acceso a datos / escritura de datos en el hash es O (1).


Apoyo todas las respuestas relacionadas con tener alguna herramienta o ejecutar la expresión Lua.

Una opción más de mi lado:

En nuestras bases de datos de producción y preproducción hay miles de claves. De vez en cuando necesitamos eliminar algunas claves (por alguna máscara), modificarlas según algún criterio, etc. Por supuesto, no hay forma de hacerlo manualmente desde CLI, especialmente con fragmentación (512 dbs lógicas en cada examen físico).

Para ello escribo una herramienta de cliente java que hace todo este trabajo. En caso de eliminación de claves, la utilidad puede ser muy simple, solo una clase allí:

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


Aquí hay una versión completamente funcional y atómica de una eliminación de comodín implementada en Lua. Se ejecutará mucho más rápido que la versión xargs debido a que habrá menos redes de ida y vuelta, y es completamente atómico, bloqueando cualquier otra solicitud contra redis hasta que finalice. Si desea eliminar las claves de forma atómica en Redis 2.6.0 o superior, este es definitivamente el camino a seguir:

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

Esta es una versión de trabajo de la idea de @mcdizzle en su respuesta a esta pregunta. El crédito por la idea le corresponde al 100%.

EDITAR: según el comentario de Kikito a continuación, si tiene más claves para eliminar que la memoria libre en su servidor Redis, encontrará el error "hay demasiados elementos para descomprimir" . En ese caso, haz:

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

Como Kikito sugirió.



Ejecutar en bash:

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

ACTUALIZAR

Está bien lo entendí. De esta manera: almacene el prefijo incremental adicional actual y agréguelo a todas sus claves. Por ejemplo:

Tienes valores como este:

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

Cuando necesita purgar datos, primero cambia prefix_actuall (por ejemplo, set prefix_prefix_actuall = 3), por lo que su aplicación escribirá nuevos datos en las teclas prefijo: 3: 1 y prefijo: 3: 2. Luego puede tomar con seguridad los valores antiguos del prefijo: 2: 1 y el prefijo: 2: 2 y purgar las claves antiguas.


Es simple implementado a través de la funcionalidad "Eliminar rama" en FastoRedis , simplemente seleccione la rama que desea eliminar.


Esta no es una respuesta directa a la pregunta, pero desde que llegué al buscar mis propias respuestas, compartiré esto aquí.

Si tiene decenas o cientos de millones de claves con las que tiene que coincidir, las respuestas que se dan aquí harán que Redis no responda por una cantidad de tiempo significativa (¿minutos?), Y posiblemente se bloquee debido al consumo de memoria (asegúrese de que el guardado en segundo plano) patear en medio de su operación).

El siguiente enfoque es innegablemente feo, pero no encontré uno mejor. La atomicidad está fuera de discusión aquí, en este caso el objetivo principal es mantener a Redis activo y receptivo el 100% del tiempo. Funcionará perfectamente si tiene todas sus claves en una de las bases de datos y no necesita coincidir con ningún patrón, pero no puede usar http://redis.io/commands/FLUSHDB debido a su naturaleza de bloqueo.

La idea es simple: escriba un script que se ejecute en un bucle y use la operación O (1) como SCAN o http://redis.io/commands/RANDOMKEY para obtener las claves, verifique si haga coincidir el patrón (si lo necesita) y http://redis.io/commands/DEL les uno por uno.

Si hay una mejor manera de hacerlo, hágamelo saber, actualizaré la respuesta.

Ejemplo de implementación con randomkey en Ruby, como tarea de rake, un sustituto sin bloqueo de algo como 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


Estoy usando el siguiente comando en redis 3.2.8

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

Puede obtener más ayuda relacionada con la búsqueda de patrones de teclas desde aquí: - https://redis.io/commands/keys . Use su patrón de estilo *YOUR_KEY_PREFIX* conveniente según su requisito como *YOUR_KEY_PREFIX* o YOUR_KEY_PREFIX?? o cualquier otro.

Y si alguno de ustedes ha integrado la biblioteca PHP de Redis, la siguiente función le ayudará.

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

Gracias :)


La respuesta de @ itamar es genial, pero el análisis de la respuesta no funcionó para mí, especialmente. en el caso de que no se encuentren claves en un escaneo dado. Una solución posiblemente más simple, directamente desde la consola:

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

Esto también utiliza SCAN, que es preferible a KEYS en producción, pero no es atómico.


La solución de @mcdizle no funciona, solo funciona para una entrada.

Esta funciona para todas las teclas con el mismo prefijo.

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

Nota: debe reemplazar ''prefijo'' con su prefijo de clave ...


Para aquellos que estaban teniendo problemas para analizar otras respuestas:

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

Reemplace la key:*:pattern con su propio patrón e ingrese esto en redis-cli y redis-cli para redis-cli .

Crédito lisco desde: http://redis.io/commands/del


Para tu información

  • solo usando bash y redis-cli
  • no usar keys (esto usa scan )
  • funciona bien en modo cluster
  • no atómico

Tal vez solo necesitas modificar los caracteres en mayúscula.

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

Ejecutar en el bash prompt

$ ./clear-redis-key.sh key_head_pattern


Si tiene espacio en el nombre de las claves, puede usar esto en bash:

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


Spring RedisTemplate proporciona la funcionalidad. RedissonClient en la última versión ha desaprobado la funcionalidad "deleteByPattern".

Set<String> keys = redisTemplate.keys("geotag|*"); redisTemplate.delete(keys);


Una versión que usa SCAN en lugar de KEYS (como se recomienda para servidores de producción) y --pipe lugar de xargs.

Prefiero canalizar sobre xargs porque es más eficiente y funciona cuando sus claves contienen comillas u otros caracteres especiales que su shell intenta e interpreta. La sustitución de expresiones regulares en este ejemplo ajusta la clave entre comillas dobles y escapa de las comillas dobles que contiene.

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


masa atómica del pobre hombre-borrar?

tal vez podría configurarlos todos para EXPIREAR el mismo segundo, como unos minutos en el futuro, y luego esperar hasta ese momento y verlos a todos "autodestruirse" al mismo tiempo.

pero no estoy realmente seguro de cuán atómico sería eso.


redis-cli keys "*prefix*" funcionan para mí


Descargo de responsabilidad: la siguiente solución no proporciona atomicidad.

Comenzando con v2.8, realmente desea utilizar el comando SCAN lugar de KEYS [1]. El siguiente script de Bash demuestra la eliminación de claves por patrón:

#!/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 es un comando peligroso que puede potencialmente resultar en un DoS. Lo siguiente es una cita de su página de documentación:

Advertencia: considere KEYS como un comando que solo debe usarse en entornos de producción con extremo cuidado. Puede arruinar el rendimiento cuando se ejecuta contra grandes bases de datos. Este comando está destinado a operaciones de depuración y especiales, como cambiar el diseño de su espacio de teclas. No use KEYS en su código de aplicación regular. Si está buscando una manera de encontrar claves en un subconjunto de su espacio de claves, considere usar conjuntos.

ACTUALIZACIÓN: un forro para el mismo efecto básico -

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


También puedes usar este comando para borrar las teclas:

Supongamos que hay muchos tipos de claves en tu redis como-

  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 '' aquí xyz es un nombre de sitio, y estas claves están relacionadas con los productos y categorías de un sitio de comercio electrónico y son generadas por FPC.

Si usa este comando como abajo

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

O

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

Borra todas las claves como '' xyz_category_fpc '' (borra 1, 2 y 3 claves). Para eliminar otras teclas numéricas de 4, 5 y 6, use '' xyz_product_fpc '' en el comando anterior.

Si desea eliminar todo en Redis , siga estos comandos:

Con redis-cli:

  1. FLUSHDB : elimina los datos de la base de datos ACTUAL de su conexión.
  2. FLUSHALL - Elimina datos de TODAS las bases de datos.

Por ejemplo: - en su shell:

redis-cli flushall redis-cli flushdb