내 Redis DB에는 많은 prefix:<numeric_id>
해시가 있습니다.
때때로 나는 그것들을 모두 원자 적으로 제거하고 싶습니다. 분산 잠금 메커니즘을 사용하지 않고 어떻게해야합니까?
내 Redis 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_*]
경고 : Redis 문서에서 알 수 있듯이 성능 문제로 인해
keys
명령은 프로덕션 환경에서 일반 작업에 사용해서는 안되며이 명령은 디버깅 및 특수 작업에 사용됩니다. 더 읽어보기
EVAL 문서를 참조하십시오 .
EVAL "local keys = redis.call('keys', ARGV[1]) \n for i=1,#keys,5000 do \n redis.call('del', unpack(keys, i, math.min(i+4999, #keys))) \n end \n return keys" 0 prefix:*
del prefix:*
기본적인 작업이어야합니다 : /
EVAL "return redis.call('del', 'defaultKey', unpack(redis.call('keys', ARGV[1])))" 0 prefix:*
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에 새 데이터를 씁니다. 그런 다음 접두사 : 2 : 1 및 접두사 : 2 : 2에서 이전 값을 안전하게 가져오고 이전 키를 제거 할 수 있습니다.
redis-cli KEYS "prefix:*" | xargs --delim='\n' redis-cli DEL
redis-cli -n 3 KEYS "prefix:*" | xargs redis-cli -n 3 DEL
다음은 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
키키 토가 제안한대로.
for _,k in ipairs(redis.call('keys', KEYS[1])) do redis.call('del', k) end
unpack
는 테이블을 "독립 변수 목록"(다른 언어로 호출 explode
)으로 변환하지만 최대 수는 시스템 메모리에 의존하지 않습니다. LUAI_MAXSTACK
상수를 통해 루아로 고정됩니다 . Lua 5.1 및 LuaJIT에서는 8000이고 Lua 5.2에서는 100000입니다. for 루프 옵션은 IMO를 권장합니다.
EVAL
은 작동하는 키를 미리 지정하지 않으므로 의미를 위반합니다 . 단일 인스턴스에서는 작동하지만 Redis 클러스터에서는 작동하지 않을 것으로 예상됩니다.
면책 조항 : 다음 솔루션 은 원 자성을 제공 하지 않습니다 .
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는 매우주의해서 프로덕션 환경에서만 사용해야하는 명령으로 간주하십시오. 큰 데이터베이스에 대해 실행될 때 성능이 저하 될 수 있습니다. 이 명령은 키 스페이스 레이아웃 변경과 같은 디버깅 및 특수 작업을위한 것입니다. 일반 응용 프로그램 코드에서 키를 사용하지 마십시오. 키 공간의 하위 세트에서 키를 찾는 방법을 찾고 있다면 세트 사용을 고려하십시오.
업데이트 : 동일한 기본 효과에 대한 하나의 라이너-
$ redis-cli --scan --pattern "*:foo:bar:*" | xargs -L 100 redis-cli DEL
-n 1
각 redis-cli
호출 에 추가 해야했습니다 .redis-cli -n 1 --scan --pattern "*:foo:bar:*" | xargs -L 100 redis-cli -n 1 DEL
다른 답변을 파싱하는 데 어려움이있는 사람들을 위해 :
eval "for _,k in ipairs(redis.call('keys','key:*:pattern')) do redis.call('del',k) end" 0
대체 key:*:pattern
자신의 패턴과이 점을 입력 redis-cli
하고 당신은 갈 수 있습니다.
신용 출처 : http://redis.io/commands/del
redis 3.2.8에서 아래 명령을 사용하고 있습니다.
redis-cli KEYS *YOUR_KEY_PREFIX* | xargs redis-cli DEL
키 패턴 검색과 관련된 추가 도움말은 여기 ( https://redis.io/commands/keys) 에서 얻을 수 있습니다 . 같은 사용자의 요구 사항에 따라 사용자의 편리 글로브 스타일의 패턴을 사용 *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);
}
}
감사합니다 :)
이 명령을 사용하여 키를 삭제할 수도 있습니다.
Redis에 많은 유형의 키가 있다고 가정합니다.
Exyz ' xyz_category_fpc '여기서 xyz 는 sitename 이며 이러한 키는 전자 상거래 사이트의 제품 및 범주와 관련이 있으며 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 '를 사용하십시오 .
당신이 할 경우 모든 삭제 에 레디 스 , 다음이 Commands-에 따라
redis-cli로 :
예를 들면 다음과 같습니다.
redis-cli flushall
redis-cli flushdb
redis-cli del
은 원자가 아닙니다.
방금 같은 문제가있었습니다. 사용자의 세션 데이터를 다음 형식으로 저장했습니다.
session:sessionid:key-x - value of x
session:sessionid:key-y - value of y
session:sessionid:key-z - value of z
따라서 각 항목은 별도의 키-값 쌍이었습니다. 세션이 파괴되면 패턴이있는 키를 삭제하여 모든 세션 데이터를 제거하고 싶었지만 session:sessionid:*
redis에는 그러한 기능이 없습니다.
내가 한 일 : 세션 데이터를 해시 내에 저장하십시오 . 난 그냥의 해시 ID로 해시를 생성 session:sessionid
한 후 내가 밀어 key-x
, key-y
, key-z
그 해시 (순서는 나에게 중요하지 않았다) 나는 해시 더 이상 난 그냥 할 것을 요구 해달라고하면 DEL session:sessionid
그 해시 ID와 관련된 모든 데이터가 사라합니다. DEL
원자 적이며 데이터에 액세스 / 해시 데이터 쓰기는 O (1)입니다.
나는 당신을 도울 수있는 것이 MULTI / EXEC / DISCARD 라고 생각합니다 . 트랜잭션과 100 % 동일 하지는 않지만 삭제를 다른 업데이트와 분리 할 수 있어야합니다.
참고로
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
bash 프롬프트에서 실행
$ ./clear-redis-key.sh key_head_pattern
키에 특수 문자가 포함되어 있으면 다른 답변이 작동하지 않을 수 있습니다 Guide$CLASSMETADATA][1]
. 각 키를 따옴표로 묶으면 올바르게 삭제됩니다.
redis-cli --scan --pattern sf_* | awk '{print $1}' | sed "s/^/'/;s/$/'/" | xargs redis-cli del
프로덕션 서버에 권장되는 KEYS --pipe
대신 xargs가 아닌 SCAN을 사용하는 버전 입니다.
나는 xargs보다 파이프를 선호합니다. 왜냐하면 키가 따옴표 또는 쉘이 시도하고 해석하는 다른 특수 문자를 포함 할 때 더 효율적이며 작동하기 때문입니다. 이 예제에서 정규식 대체는 키를 큰 따옴표로 묶고 큰 따옴표를 이스케이프 처리합니다.
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가 상당한 시간 (분) 동안 응답하지 않고 메모리 소비로 인해 충돌이 발생할 수 있습니다 (백그라운드 저장은 작업 중간에 시작하십시오).
다음 접근 방식은 명백히 추악하지만 더 나은 방법을 찾지 못했습니다. Atomicity는 여기서 의문의 여지가 없습니다.이 경우 주된 목표는 Redis를 100 % 응답하고 유지하는 것입니다. 데이터베이스 중 하나에 모든 키가 있고 어떤 패턴과도 일치하지 않아도 완벽하게 작동하지만 차단 특성으로 인해 http://redis.io/commands/FLUSHDB를 사용할 수 없습니다 .
아이디어는 간단합니다. 루프에서 실행되고 http://redis.io/commands/SCAN 또는 http://redis.io/commands/RANDOMKEY 와 같은 O (1) 연산 을 사용하여 키를 가져 오는 스크립트를 작성하십시오. 패턴 (필요한 경우)과 http://redis.io/commands/DEL 을 하나씩 일치시킵니다 .
더 좋은 방법이 있으면 알려주세요. 답변을 업데이트하겠습니다.
Ruby에서 randomkey를 사용한 예제 구현은 레이크 작업으로 다음과 같은 비 차단 대체물입니다 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
FastoRedis의 "브랜치 제거"기능을 통해 간단하게 구현할 수 있습니다. 제거하려는 브랜치를 선택하기 만하면 됩니다.
이 명령을 사용하고 시도하십시오 :
redis-cli --raw keys "$PATTERN" | xargs redis-cli del
위에서 언급 한 대부분의 방법을 시도했지만 일부 검색 후이 점을 발견 한 후에는 효과가 없었습니다.
-n [number]
del
하지만 수천 또는 수백만 개의 키가있는 경우 del이 차단되는 동안 unlink는 비 차단unlink
이기 때문에 사용하는 것이 좋습니다. 자세한 내용은이 페이지를 방문하십시오 unlink vs delkeys
델과 같고 차단 중입니다.그래서이 코드를 사용하여 패턴별로 키를 삭제했습니다.
redis-cli -n 2 --scan --pattern '[your pattern]' | xargs redis-cli -n 2 unlink
도구를 사용하거나 Lua 식을 실행하는 것과 관련된 모든 답변을 지원합니다.
내 편에서 한 가지 더 옵션 :
프로덕션 및 프로덕션 전 데이터베이스에는 수천 개의 키가 있습니다. 때때로 우리는 일부 키 (일부 마스크로)를 삭제하고 일부 기준으로 수정해야합니다. 물론, 특히 샤딩 (각 물리적마다 512 개의 논리적 DB)을 갖는 CLI에서 수동으로 수행 할 수있는 방법이 없습니다.
이를 위해이 모든 작업을 수행하는 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();
}
}
Spring RedisTemplate 자체가 기능을 제공합니다. 최신 버전의 RedissonClient는 "deleteByPattern"기능을 더 이상 사용하지 않습니다.
Set<String> keys = redisTemplate.keys("geotag|*");
redisTemplate.delete(keys);
keys
및 delete
메소드 호출은.