在我的Redis DB中,我有一些前缀:<numeric_id>哈希值。

有时我想把它们都原子地清除掉。如何在不使用分布式锁定机制的情况下做到这一点呢?


当前回答

我想可能对你有帮助的是MULTI/EXEC/DISCARD。虽然不是100%等同于事务,但您应该能够将删除与其他更新隔离开来。

其他回答

FYI.

只使用bash和redis-cli 不使用键(这使用扫描) 在集群模式下工作良好 不是原子

也许您只需要修改大写字符。

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

我支持所有与有一些工具或执行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();
    }

}

在bash执行:

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

更新

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

你的价值观是这样的:

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

当您需要清除数据时,首先更改prefix_actuall(例如set prefix_prefix_actuall = 3),因此您的应用程序将把新数据写入关键字prefix:3:1和prefix:3:2。然后,您可以安全地从prefix:2:1和prefix:2:2中获取旧值并清除旧键。

如果你使用的是Redis版本低于4,你可以试试

redis-cli -h 127.0.0.1 -p 26379 -a `yourPassword` --scan --pattern data:* | xargs redis-cli del

如果你正在使用以上4个版本,那么

redis-cli -h 127.0.0.1 -p 26379 -a `yourPassword` --scan --pattern data:*| xargs redis-cli unlink

为了检查你的版本,使用以下命令进入你的Redis终端

redis-cli -h 127.0.0.1 -p 26379 -a `yourPassword

然后输入

> INFO

# Server
redis_version:5.0.5
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:da75abdfe06a50f8
redis_mode:standalone
os:Linux 5.3.0-51-generic x86_64
arch_bits:64
multiplexing_api:epoll
atomicvar_api:atomic-builtin
gcc_version:7.5.0
process_id:14126
run_id:adfaeec5683d7381a2a175a2111f6159b6342830
tcp_port:6379
uptime_in_seconds:16860
uptime_in_days:0
hz:10
configured_hz:10
lru_clock:15766886
executable:/tmp/redis-5.0.5/src/redis-server
config_file:

# Clients
connected_clients:22
....More Verbose

这是不用任何xargs魔法就能想到的最简单的方法

纯bash !

redis-cli DEL $(redis-cli KEYS *pattern*)