在我的Redis DB中,我有一些前缀:<numeric_id>哈希值。
有时我想把它们都原子地清除掉。如何在不使用分布式锁定机制的情况下做到这一点呢?
在我的Redis DB中,我有一些前缀:<numeric_id>哈希值。
有时我想把它们都原子地清除掉。如何在不使用分布式锁定机制的情况下做到这一点呢?
当前回答
我支持所有与有一些工具或执行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中有很多类型的键,比如-
“xyz_category_fpc_12” “xyz_category_fpc_245” “xyz_category_fpc_321” “xyz_product_fpc_876” “xyz_product_fpc_302” “xyz_product_fpc_01232”
Ex- 'xyz_category_fpc'这里xyz是一个站点名称,这些键与电子商务网站的产品和类别相关,由FPC生成。
如果您像下面那样使用此命令-
redis-cli --scan --pattern 'key*' | xargs redis-cli del
OR
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:
FLUSHDB -从连接的当前数据库中删除数据。 FLUSHALL—从所有数据库中删除数据。
例如:-在你的壳:
redis-cli flushall
redis-cli flushdb
从redis 2.6.0开始,你可以运行lua脚本,它以原子方式执行。我从来没有写过,但我想应该是这样的
EVAL "return redis.call('del', unpack(redis.call('keys', ARGV[1])))" 0 prefix:[YOUR_PREFIX e.g delete_me_*]
警告:正如Redis文档所说,由于性能问题,关键字 命令不应用于生产中的常规操作,此 命令用于调试和特殊操作。读 更多的
请参阅EVAL文档。
下面是一个用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所建议的。
对于那些无法解析其他答案的人:
eval "for _,k in ipairs(redis.call('keys','key:*:pattern')) do redis.call('del',k) end" 0
将key:*:pattern替换为您自己的模式,并将其输入到redis-cli中,就可以开始了。
Credit lisco来自:http://redis.io/commands/del