Question Comment supprimer de façon atomique les touches correspondant à un motif en utilisant Redis


Dans ma Redis DB, j'ai un certain nombre de prefix:<numeric_id> hashes.

Parfois, je veux les purger tous atomiquement. Comment puis-je faire cela sans utiliser un mécanisme de verrouillage distribué?


451
2017-10-23 22:04


origine


Réponses:


À partir de redis 2.6.0, vous pouvez exécuter des scripts lua, qui s'exécutent de manière atomique. Je n'en ai jamais écrit, mais je pense que ça ressemblerait à ça

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

Voir le Documentation EVAL.


335
2018-06-06 23:47



Exécuter dans bash:

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

METTRE À JOUR

Ok j'ai compris. Qu'en est-il de cette façon: stocker le préfixe incrémental supplémentaire actuel et l'ajouter à toutes vos clés. Par exemple:

Vous avez des valeurs comme celle-ci:

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

Lorsque vous devez purger des données, vous devez d'abord changer prefix_actuall (par exemple set prefix_prefix_actuall = 3), afin que votre application écrira de nouvelles données dans le préfixe keys: 3: 1 et le préfixe: 3: 2. Ensuite, vous pouvez prendre en toute sécurité les anciennes valeurs du préfixe: 2: 1 et le préfixe: 2: 2 et purger les anciennes clés.


608
2018-06-10 04:20



Voici une version complètement fonctionnelle et atomique d'une suppression générique implémentée dans Lua. Il fonctionnera beaucoup plus vite que la version de xargs en raison de beaucoup moins de va-et-vient réseau, et il est complètement atomique, bloquant toutes les autres demandes contre redis jusqu'à ce qu'il se termine. Si vous voulez supprimer des clés de manière reduite sur Redis 2.6.0 ou supérieur, c'est définitivement le chemin à parcourir:

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

Ceci est une version de travail de l'idée de @ mcdizzle dans sa réponse à cette question. Crédit pour l'idée 100% va à lui.

MODIFIER: Voici le commentaire de Per Kikito ci-dessous, si vous avez plus de clés à supprimer que de mémoire libre sur votre serveur Redis, vous allez rencontrer "trop ​​d'éléments à décompresser" erreur. Dans ce cas, faites:

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

Comme Kikito l'a suggéré.


65
2018-04-30 22:26



Disclaimer: la solution suivante ne pas fournir de l'atomicité.

À partir de v2.8 vous vraiment vouloir utiliser le BALAYAGE commande au lieu de KEYS [1]. Le script Bash suivant illustre la suppression des clés par pattern:

#!/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] CLÉS est une commande dangereuse pouvant entraîner un déni de service. Voici un extrait de sa page de documentation:

Attention: Considérez KEYS comme une commande qui ne devrait être utilisée dans les environnements de production qu'avec un soin extrême. Cela peut ruiner les performances quand il est exécuté sur des bases de données volumineuses. Cette commande est destinée au débogage et aux opérations spéciales, telles que la modification de la disposition de votre espace de clé. N'utilisez pas KEYS dans votre code d'application habituel. Si vous cherchez un moyen de trouver des clés dans un sous-ensemble de votre espace de clés, pensez à utiliser des ensembles.

METTRE À JOUR: un seul revêtement pour le même effet de base -

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

49
2018-03-19 15:32



Pour ceux qui éprouvaient des difficultés à analyser d'autres réponses:

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

Remplacer key:*:pattern avec votre propre modèle et entrez ceci dans redis-cli et vous êtes bon à faire.

Crédit lisco de: http://redis.io/commands/del


25
2018-05-08 07:33



J'utilise la commande ci-dessous dans redis 3.2.8

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

Vous pouvez obtenir plus d'aide concernant la recherche de modèles de clés à partir d'ici: - https://redis.io/commands/keys. Utilisez votre modèle de style glob globalement selon vos besoins comme *YOUR_KEY_PREFIX* ou YOUR_KEY_PREFIX?? ou tout autre.

Et si l'un de vous a intégré Bibliothèque PHP Redis que la fonction ci-dessous vous aidera.

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

Je vous remercie :)


23
2017-12-19 07:20



La solution de @ mcdizle ne fonctionne pas, elle ne fonctionne que pour une seule entrée.

Celui-ci fonctionne pour toutes les clés avec le même préfixe

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

Remarque: Vous devez remplacer "préfixe" par votre préfixe clé ...


14
2018-03-04 23:48



Si vous avez de l'espace dans le nom des clés, vous pouvez l'utiliser dans bash:

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

11
2018-06-23 02:18



La réponse de @ itamar est excellente, mais l'analyse de la réponse n'a pas fonctionné pour moi, en particulier. dans le cas où il n'y a pas de clés trouvées dans un scan donné. Une solution peut-être plus simple, directement depuis la console:

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

Cela utilise également SCAN, ce qui est préférable à KEYS en production, mais n'est pas atomique.


9
2018-01-12 18:31