如何自动删除使用Redis匹配模式的密钥

在我的Redis DB中,我有一些prefix:<numeric_id>散列。

有时候我想把它们全部清理干净。 我如何做到这一点,而不使用一些分布式locking机制?

从redis 2.6.0开始,你可以运行primefaces执行的lua脚本。 我从来没有写过,但我认为它看起来像这样

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

请参阅EVAL文档 。

在bash中执行:

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

UPDATE

好,我明白了。 这样的方式:存储当前额外的增量前缀,并将其添加到您的所有密钥。 例如:

你有这样的价值观:

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

当您需要清除数据时,首先更改prefix_actuall(例如设置prefix_prefix_actuall = 3),以便您的应用程序将新密钥写入前缀:3:1和前缀:3:2。 然后,您可以安全地从前缀:2:1和前缀:2:2旧值,并清除旧的密钥。

这是一个在Lua中实现的通配符删除的完整工作primefaces版本。 它会比xargs版本运行得更快,原因是networking来回更less,而且它是完全primefaces的,阻止任何其他对redis的请求,直到完成。 如果你想自动删除Redis 2.6.0或更高版本上的密钥,这绝对是一种方式:

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

这是@ mcdizzle的想法在他回答这个问题的工作版本。 信用的想法100%去他。

编辑:每Kikito的评论下面,如果你有更多的关键要删除您的Redis服务器中的空闲内存,你会遇到“太多元素解压缩”的错误 。 在这种情况下,请执行:

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

正如Kikito所build议的那样。

免责声明:以下解决scheme提供primefaces性。

从v2.8开始,你真的想用SCAN命令代替KEYS [1]。 以下Bash脚本演示按模式删除键:

 #!/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是一个危险的命令,可能会导致DoS。 以下是其文档页面的引用:

警告:将KEYS看作只能在生产环境中谨慎使用的命令。 对大型数据库执行操作可能会导致性能下降。 此命令用于debugging和特殊操作,例如更改您的键盘空间布局。 不要在您的常规应用程序代码中使用KEYS。 如果您正在寻找一种方法在您的密钥空间的子集中查找密钥,请考虑使用集合。

更新:一个class轮相同的基本效果 –

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

对于那些parsing其他答案时遇到问题的人:

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

用你自己的模式replacekey:*:pattern ,并将其input到redis-cli并且你很好。

学分来自: http ://redis.io/commands/del

@ mcdizle的解决scheme不起作用,只适用于一个条目。

这个适用于所有具有相同前缀的密钥

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

注意:您应该用您的密钥前缀replace“前缀”…

如果你的键名有空格,你可以在bash中使用它:

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

@ itamar的回答很好,但是答复的parsing不适合我, 在给定的扫描中没有find密钥的情况下。 一个可能更简单的解决scheme,直接从控制台:

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

这也使用SCAN,它比生产中的KEYS更好,但不是primefaces的。

我在redis 3.2.8中使用下面的命令

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

您可以从这里获得更多与按键模式search相关的帮助: https : //redis.io/commands/keys 。 根据您的要求使用您的方便的全局样式模式,如*YOUR_KEY_PREFIX*YOUR_KEY_PREFIX?? 或任何其他。

如果你有任何一个集成的Redis PHP库比下面的function将帮助你。

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

谢谢 :)

我认为可以帮助你的是MULTI / EXEC / DISCARD 。 尽pipe不是100%的交易 ,但您应该能够将删除与其他更新隔离开来。

我只是有同样的问题。 我以下面的格式存储用户的会话数据:

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

所以,每个条目都是一个单独的键值对。 当会话被销毁时,我想通过删除模式session:sessionid:*键来删除所有会话数据session:sessionid:* – 但是redis没有这样的function。

我做了什么:将会话数据存储在一个散列中 。 我只是使用session:sessionid的哈希ID创build一个哈希,然后我在这个哈希中按key-xkey-ykey-z (顺序对我没有关系),如果我不需要这个哈希了,我只是做一个DEL session:sessionid和与该哈希id关联的所有数据都消失了。 DEL是primefaces,访问数据/写入数据的散列是O(1)。

您也可以使用此命令来删除密钥: –

假设你的redis中有许多types的键,

  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 '这里xyz是一个网站名称 ,这些密钥与电子商务网站的产品和类别有关,由FPC生成。

如果你使用这个命令如下 –

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

要么

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

它删除所有的键,如' xyz_category_fpc '(删除1,2和3键)。 要删除其他4,5和6个数字键,请使用上述命令中的“ xyz_product_fpc ”。

如果您要删除 Redis中的所有内容 ,请按照以下命令 –

使用redis-cli:

  1. FLUSHDB – 从连接的CURRENT数据库中删除数据。
  2. FLUSHALL – 从所有数据库中删除数据。

例如: – 在你的shell中:

 redis-cli flushall redis-cli flushdb 

仅供参考。

  • 只使用bash和redis-cli
  • 不使用keys (这使用scan
  • 集群模式下运行良好
  • 不是primefaces的

也许你只需要修改大写字母。

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 

在bash提示符下运行

 $ ./clear-redis-key.sh key_head_pattern 

这不是直接回答这个问题,但是因为我在寻找自己的答案时到了这里,所以我会在这里分享一下。

如果您必须匹配数十万或数百万个密钥,则此处给出的答案将导致Redis在大量时间(分钟?)内无法响应,并可能由于内存消耗而崩溃(请确保后台保存将会踢在你的手术中)。

下面的方法无疑是丑陋的,但我没有find一个更好的。 primefaces性在这里是没有问题的,在这种情况下,主要目标是保持Redis 100%的响应时间。 如果你把所有的密钥都放在一个数据库中,并且你不需要匹配任何模式,但是由于阻塞性质,不能使用http://redis.io/commands/FLUSHDB

想法很简单:编写一个循环运行的脚本,并使用O(1)操作,如http://redis.io/commands/SCAN或http://redis.io/commands/RANDOMKEY获取密钥,检查它们匹配的模式(如果你需要它)和http://redis.io/commands/DEL他们一个接一个。;

如果有更好的办法,请让我知道,我会更新答案。

在Ruby中使用randomkey的示例实现,作为rake任务,像redis-cli -n 3 flushdb非阻塞replaceredis-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 

我支持所有有关有一些工具或执行Luaexpression式的答案。

我的另一个select:

在我们的生产和预生产数据库中有数千个密钥。 有时候我们需要删除一些密钥(通过掩码),修改一些标准等。当然,没有办法从CLI手动执行,特别是分片(每个物理中有512个逻辑数据块)。

为此,我编写了Java客户端工具来完成所有这些工作。 在删除键的情况下,实用程序可以非常简单,只有一个类:

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

一个版本使用SCAN而不是KEYS(推荐用于生产服务器)和 – --pipe而不是xargs。

我更喜欢pipe道xargs,因为它更有效率,并且当你的键包含引号或其他特殊字符,你的shell与尝试和解释工程。 在这个例子中的正则expression式replace包含在双引号的关键,并转义任何内部的双引号。

 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 

穷人的primefaces量 – 删除?

也许你可以把他们全部设置为EXPIREAT同样的时间 – 就像将来的几分钟 – 然后等到那个时候,看到他们都在同一时间“自我毁灭”。

但是我不太确定那将会是怎样的primefaces。

Spring RedisTemplate本身提供了这个function。 最新版本的RedissonClient已弃用“deleteByPattern”function。

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

redis-cli keys "*prefix*"为我工作