题
在我穿红衣DB我有一个号码的 prefix:<numeric_id>
哈希。
有时候我想要清除他们所有的原子我怎么这没有使用的一些分布的锁定机制?
解决方案
使用Redis的2.6.0开始,你可以运行Lua脚本,它执行原子。我从来没有写过一个,但我认为这会是这个样子
EVAL "return redis.call('del', unpack(redis.call('keys', ARGV[1])))" 0 prefix:[YOUR_PREFIX e.g delete_me_*]
请参阅 EVAL文档。
其他提示
执行在bash:
redis-cli KEYS "prefix:*" | xargs redis-cli DEL
<强>更新强>
好,我理解。什么是这样的:店面当前的额外增加的前缀,并将其添加到您的所有钥匙。例如:
您有值是这样的:
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删除实现。它会因少得多网络备份和来回远远超过了xargs的版本运行速度,而且完全原子,阻止任何其他请求对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建议。
声明:下述溶液的不强>提供原子
与2.8版开始,你的真的要使用的 SCAN 命令来代替键[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为应该仅在非常小心的生产环境中使用的命令。当对大型数据库执行它可能会毁性能。这个命令是用于调试和特种作战,如更改密钥空间布局。请不要在普通的应用程序代码中使用的密钥。如果你正在寻找一种方式来找到你的密钥空间的一个子集密钥,可以考虑使用套。
<强>更新强>一和衬里相同的基本效果 -
$ redis-cli --scan --pattern "*:foo:bar:*" | xargs -L 100 redis-cli DEL
有关那些谁是有麻烦解析其他答案:
eval "for _,k in ipairs(redis.call('keys','key:*:pattern')) do redis.call('del',k) end" 0
替换key:*:pattern
用自己的方式,进入redis-cli
这一点,你是好去。
信用LISCO从: http://redis.io/commands/del
我在redis的使用以下命令3.2.8
redis-cli KEYS *YOUR_KEY_PREFIX* | xargs redis-cli DEL
https://redis.io/commands/ - 您可以得到更多的帮助,从这里涉及到的键模式搜索键
的。用你的方便通配符式样的图案,按您的要求例如*YOUR_KEY_PREFIX*
或 YOUR_KEY_PREFIX??
或任何其他。
和如果你们已经整合的 Redis的PHP库比下面的功能将帮助你。
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);
}
}
感谢您:)
@ mcdizle的解决方案是行不通的它仅适用于一个项目。
这一个适用于与相同前缀
的所有键EVAL "for i, name in ipairs(redis.call('KEYS', ARGV[1])) do redis.call('DEL', name); end" 0 prefix*
注意:您应该与你的钥匙替换 '前缀' 前缀......
你也可以使用此命令删除的项:-
假设有许多类型的钥匙,在你的节点像
- 'xyz_category_fpc_12'
- 'xyz_category_fpc_245'
- 'xyz_category_fpc_321'
- 'xyz_product_fpc_876'
- 'xyz_product_fpc_302'
- 'xyz_product_fpc_01232'
前'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'在上面的命令。
如果你想要 删除的一切 在 穿红衣, 然后按照这些命令
有穿红衣-cli:
- FLUSHDB -删除的数据,从您的连接目前的数据库。
- FLUSHALL -删除的数据,从所有数据库。
例如:-在你的外壳:
redis-cli flushall
redis-cli flushdb
如果您在按键的名字空间,你可以在bash使用这样的:
redis-cli keys "pattern: *" | xargs -L1 -I '$' echo '"$"' | xargs redis-cli del
@伊塔马尔的答案是伟大的,但答复的分析并没有为我工作,ESP。在该情况下没有在给定的扫描发现钥匙。一个可能简单的解决方案,直接从控制台:
redis-cli -h HOST -p PORT --scan --pattern "prefix:*" | xargs -n 100 redis-cli DEL
此也使用SCAN,这是优选的,以在生产键,但不是原子。
我刚刚有同样的问题。余存储的会话数据在格式的用户:
session:sessionid:key-x - value of x
session:sessionid:key-y - value of y
session:sessionid:key-z - value of z
因此,每个条目是一个单独的键 - 值对。当会话被破坏时,我想通过删除与所述图案session:sessionid:*
键以除去所有会话数据 - 但Redis的不具有这样的功能
我做了什么:存储中的会话的数据的哈希。我只是创建一个哈希与session:sessionid
的哈希ID,然后我推key-x
,key-y
,key-z
在哈希(为了没事情我),如果我不需要散列了我只是做了DEL session:sessionid
和与之相关的所有数据哈希ID消失了。 DEL
是原子和访问数据/将数据写入到所述散列是O(1)。
供你参考。
- 只有使用和bash
redis-cli
- 不使用
keys
(这一用scan
) - 工作良好 群集方式
- 不是原子
也许你只需要修改资本字。
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
运行在庆典的提示
$ ./clear-redis-key.sh key_head_pattern
我想可能会帮助你的是 MULTI / EXEC /放弃。虽然不是 100%相当于交易,则应当能够在从删除其他更新相隔离。
这是通过在 FastoRedis “删除分支”的功能实现简单,只需选择要删除的分支。
请使用该命令,然后尝试:
redis-cli --raw keys "$PATTERN" | xargs redis-cli del
使用SCAN而非键(作为推荐在生产服务器)和--pipe
而非xargs的一个版本。
我更喜欢管过xargs的,因为它更高效,适用于你的密钥包含引号或其他特殊字符与尝试你的shell和解释。在这个例子中的正则表达式替换包装在双引号的关键,而逸出内部的任何双引号。
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
这是没有直接回答这个问题,但因为我对我自己的答案搜索的时候来到这里,我会在这里分享。
如果你有一个你必须匹配键的几十或几百万元,这里给出的答案会导致Redis的是无响应的显著的时间(分钟?),而且由于内存消耗可能崩溃(当然,后台保存在您的操作过程中会踢)。
在下面的方法无疑是丑陋的,但我没有找到一个更好的。原子性是毫无疑问的在这里,在这种情况下,主要目标是保持Redis的起来的响应时间的100%。这将很好地工作,如果你把所有的钥匙在数据库之一,你不必与任何模式匹配,但不能使用的 http://redis.io/commands/FLUSHDB 因为它的阻止性质。
思想非常简单:写一个脚本,如 HTTP在循环中和用途为O(1)操作:// redis.io/commands/SCAN 或 http://redis.io/commands/RANDOMKEY 拿到钥匙,检查它们是否匹配模式(如果需要的话)和 http://redis.io/commands/ DEL 的逐一。
如果有更好的方式来做到这一点,请让我知道,我会更新的答案。
实施例执行与红宝石随机key,作为前刀面的任务,的像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
我试着大多数的方法上面提到的但是他们没有为我工作之后,一些搜索的我找到这些要点:
- 如果你有多个数据库上穿红衣的你应该确定该数据库使用
-n [number]
- 如果你有一些钥匙用
del
但是,如果有数以千计或数以百万计的钥匙最好使用unlink
因 断开链接是无阻塞 同时del阻止,更多信息,请访问这个网页 取消vs del - 还
keys
就像德和阻止
所以我用这个代码删除键模式:
redis-cli -n 2 --scan --pattern '[your pattern]' | xargs redis-cli -n 2 unlink
我支持涉及具有一些工具或执行的Lua表达所有答案。
从我的侧还有一个选项:
在我们的生产和预生产数据库有成千上万的键。我们不时需要删除一些键(由一些掩模),由一些标准等。当然修改,也没有办法从CLI做手工,尤其是具有分片(在每个物理逻辑512个DBS)。
为此,我写的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();
}
}
下面命令为我工作。
redis-cli -h redis_host_url KEYS "*abcd*" | xargs redis-cli -h redis_host_url DEL
现在广告,则可以使用一个Redis的客户机和每个键分别进行第一扫描(支持模式匹配),然后DEL。
然而,在官方Redis的GitHub上的问题,以创建一个图案匹配 - 德尔这里,去表现出来一些爱,如果你觉得它有用!
穷人的原子质量,删除?
也许你可以设置他们都EXPIREAT同第二 - 就像在未来几分钟 - 然后等到那个时候,看到他们所有的“自毁”在同一时间
但我真的不知道怎么原子,这将是。
弹簧RedisTemplate本身提供的功能。 RedissonClient在最新版本已弃用“deleteByPattern”功能。
Set<String> keys = redisTemplate.keys("geotag|*");
redisTemplate.delete(keys);