在我的Redis DB中,我有一些前缀:<numeric_id>哈希值。
有时我想把它们都原子地清除掉。如何在不使用分布式锁定机制的情况下做到这一点呢?
在我的Redis DB中,我有一些前缀:<numeric_id>哈希值。
有时我想把它们都原子地清除掉。如何在不使用分布式锁定机制的情况下做到这一点呢?
当前回答
使用SCAN而不是KEYS(推荐用于生产服务器)和——pipe而不是xargs的版本。
与xargs相比,我更喜欢pipe,因为它更有效,并且在键包含引号或shell尝试和解释的其他特殊字符时也能工作。本例中的regex替换用双引号包装键,并转义其中的任何双引号。
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
其他回答
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
/ /所有
你认为这是没有意义的命令,但有时Redis命令像DEL不能正确工作,来拯救这个
redis-cli KEYS "*" | xargs -i redis-cli EXPIRE {} 1 it's life hack
Spring RedisTemplate本身提供了这个功能。RedissonClient在最新版本中已经弃用了“deletebyppattern”功能。
Set<String> keys = redisTemplate.keys("geotag|*");
redisTemplate.delete(keys);
如果你使用的是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
如果我们想要确保原子操作,我们可以尝试编写一个Lua脚本。
如果你的Redis版本支持SCAN和UNLINK(高于4.0.0),我更喜欢在生产环境中使用SCAN和UNLINK而不是Key和DEL,因为Key和DEL命令可能会阻塞
它们可以在生产环境中使用,而没有KEYS或members等命令的缺点,这些命令在针对大量键或元素集合调用时可能会阻塞服务器很长时间(甚至几秒钟)。
EVAL "local cursor = 0 repeat local result = redis.call('SCAN', cursor, 'MATCH', ARGV[1]) for _,key in ipairs(result[2]) do redis.call('UNLINK', key) end cursor = tonumber(result[1]) until cursor == 0 " 0 prefix:*
我们可以随意更改前缀:*。