복붙노트

[REDIS] 어떻게 레디 스를 사용하여 패턴과 일치하는 원자 적으로 삭제 키

REDIS

어떻게 레디 스를 사용하여 패턴과 일치하는 원자 적으로 삭제 키

내 레디 스 DB에서 나는 접두사의 번호를 가지고 : 해시.

때때로 나는 모든 원자를 제거하고 싶다. 어떻게 일부 분산 잠금 장치를 사용하지 않고 내가이 작업을 수행합니까?

해결법

  1. ==============================

    1.레디 스 2.6.0부터는 원자 적으로 실행 루아 스크립트를 실행할 수 있습니다. 나는 하나를 쓴 적이 없다,하지만 난 그것을 다음과 같이 보일 것 같아

    레디 스 2.6.0부터는 원자 적으로 실행 루아 스크립트를 실행할 수 있습니다. 나는 하나를 쓴 적이 없다,하지만 난 그것을 다음과 같이 보일 것 같아

    EVAL "return redis.call('del', unpack(redis.call('keys', ARGV[1])))" 0 prefix:[YOUR_PREFIX e.g delete_me_*]
    

    평가 후면 설명서를 참조하십시오.

  2. ==============================

    2.bash는 실행 :

    bash는 실행 :

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

    최신 정보

    알아 들었어. 이 방식에 대해 무엇 : 저장 현재 추가로 증가 접두사와 모든 키에 추가합니다. 예를 들면 :

    이 같은 값을 가진다 :

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

    당신이 퍼지 데이터를 필요로 할 때 응용 프로그램이 키에 새로운 데이터를 기록 할 수 있도록, 당신은 접두사 (예 : 세트 prefix_prefix_actuall = 3) 첫 번째 prefix_actuall 변경 : 3 : 1 접두사 : 3 : 2. : 2 : 2와 이전 키를 제거 : 1 접두사 : 2를 다음 당신은 안전하게 접두사에서 이전 값을 사용할 수 있습니다.

  3. ==============================

    3.여기의 작동을 완전히 원자 버전 루아에서 구현 삭제할 와일드 카드입니다. 이 때문에 훨씬 덜 네트워크 앞뒤로에 훨씬 빠르게 xargs를 버전보다 실행 것이고, 그것이 완료 될 때까지 레디 스에 대해 다른 요청을 차단, 완전히 원자이다. 당신은 레디 스 2.6.0 이상에 원자 적으로 삭제 키를 원하는 경우,이 갈 방법은 확실히 :

    여기의 작동을 완전히 원자 버전 루아에서 구현 삭제할 와일드 카드입니다. 이 때문에 훨씬 덜 네트워크 앞뒤로에 훨씬 빠르게 xargs를 버전보다 실행 것이고, 그것이 완료 될 때까지 레디 스에 대해 다른 요청을 차단, 완전히 원자이다. 당신은 레디 스 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의 코멘트, 당신은 당신의 레디 스 서버에서 사용 가능한 메모리보다 삭제할 ​​수있는 더 키가있는 경우, 당신은 오류 "를 풀고 너무 많은 요소"를로 실행하겠습니다. 이 경우, 수행

    for _,k in ipairs(redis.call('keys', ARGV[1])) do 
        redis.call('del', k) 
    end
    

    Kikito은 제안했다.

  4. ==============================

    4.면책 조항 : 다음과 같은 솔루션은 자성을 제공하지 않습니다.

    면책 조항 : 다음과 같은 솔루션은 자성을 제공하지 않습니다.

    V2.8 시작 당신은 정말 KEYS [1] 대신 SCAN 명령을 사용합니다. 다음 배쉬 스크립트 패턴에 의해 키의 삭제를 보여줍니다

    #!/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 잠재적 도스를 일으킬 수있는 위험한 명령이다. 다음은 설명서 페이지에서 인용 한 것입니다 :

    UPDATE : 같은 기본 효과를 한 라이너 -

    $ redis-cli --scan --pattern "*:foo:bar:*" | xargs -L 100 redis-cli DEL
    
  5. ==============================

    5.문제 분석 다른 답을 가지고 있었다 사람들을 위해 :

    문제 분석 다른 답을 가지고 있었다 사람들을 위해 :

    eval "for _,k in ipairs(redis.call('keys','key:*:pattern')) do redis.call('del',k) end" 0
    

    자신의 패턴 패턴과 레디 스-CLI에이를 입력하고 당신은 갈 수 있습니다 : * : 키 교체합니다.

    신용 lisco에서 : http://redis.io/commands/del

  6. ==============================

    6.3.2.8 레디 스에서 나는 명령 아래 사용하고 있습니다

    3.2.8 레디 스에서 나는 명령 아래 사용하고 있습니다

    redis-cli KEYS *YOUR_KEY_PREFIX* | xargs redis-cli DEL
    

    당신은 여기에서 키 패턴 검색에 관한 더 많은 도움을 얻을 수 있습니다 : - https://redis.io/commands/keys합니다. * YOUR_KEY_PREFIX * 또는 YOUR_KEY_PREFIX 같이 당신의 요구 사항에 따라 사용자의 편리 글로브 스타일의 패턴을 사용 ?? 또는 기타.

    그리고 기능 아래보다는 당신의 통합 한 경우 레디 스 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);
                }
            }
    

    감사합니다 :)

  7. ==============================

    7.@ mcdizle의 솔루션은 하나 개의 항목 만 작동 작동하지 않습니다.

    @ mcdizle의 솔루션은 하나 개의 항목 만 작동 작동하지 않습니다.

    이 사람은 같은 접두사를 가진 모든 키 작동

    EVAL "for i, name in ipairs(redis.call('KEYS', ARGV[1])) do redis.call('DEL', name); end" 0 prefix*
    

    참고 : 키 접두사로 '접두사'교체해야합니다 ...

  8. ==============================

    8.또한 키를 삭제하려면이 명령을 사용할 수 있습니다 -

    또한 키를 삭제하려면이 명령을 사용할 수 있습니다 -

    키의 많은 유형이 당신의 레디 스 같은 -에가있는 가정

    전직 'xyz_category_fpc'여기 XYZ하는 사이트 이름이며,이 키는 제품과 전자 상거래 사이트의 범주에 관련 및 FPC에 의해 생성됩니다.

    당신은 below-이 명령을 사용하는 경우

    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-에 따라

    레디 스-CLI를 :

    예를 들면 : - 쉘에서 :

    redis-cli flushall
    redis-cli flushdb
    
  9. ==============================

    9.당신은 키의 이름에 공백이있는 경우에는 떠들썩한 파티에서 이것을 사용할 수 있습니다 :

    당신은 키의 이름에 공백이있는 경우에는 떠들썩한 파티에서 이것을 사용할 수 있습니다 :

    redis-cli keys "pattern: *" | xargs -L1 -I '$' echo '"$"' | xargs redis-cli del
    
  10. ==============================

    10.@ 이타 마르의 대답은 매우 중요하지만, 응답의 구문 분석 ESP, 나를 위해 작동하지 않았다. 경우에 주어진 검사에서 발견되는 더 키가없는 경우. 직접 콘솔에서의 가능성이 간단한 해결책 :

    @ 이타 마르의 대답은 매우 중요하지만, 응답의 구문 분석 ESP, 나를 위해 작동하지 않았다. 경우에 주어진 검사에서 발견되는 더 키가없는 경우. 직접 콘솔에서의 가능성이 간단한 해결책 :

    redis-cli -h HOST -p PORT  --scan --pattern "prefix:*" | xargs -n 100 redis-cli DEL
    

    이것은 또한 생산 키 바람직하지만, 원자 아니다 SCAN을 사용한다.

  11. ==============================

    11.난 그냥 같은 문제가 있었다. 나는 형식의 사용자에 대한 세션 데이터를 저장 :

    난 그냥 같은 문제가 있었다. 나는 형식의 사용자에 대한 세션 데이터를 저장 :

    session:sessionid:key-x - value of x
    session:sessionid:key-y - value of y
    session:sessionid:key-z - value of z
    

    그래서, 각 항목은 별도의 키 - 값 쌍이었다. 세션 id를 : 세션이 파괴 될 때, 나는 패턴 세션 키를 삭제하여 모든 세션 데이터를 제거하고 싶어 * -하지만 이러한 기능이 없습니다 레디 스.

    나는 무엇 않았다 해시 내에서 세션 데이터를 저장합니다. 세션 id를하고 그 해시 키-X, 키-Y, 키-Z를 밀어 (순서는 나에게 중요하지 않았다) 나는 필요성을 해달라고하면 해시 더 이상 그냥 할 것을 : 난 그냥 세션의 해시 ID로 해시를 생성 DEL 세션 : 세션 ID와 그 해시 ID와 관련된 모든 데이터가 사라 졌어요. DEL 원자 및 데이터에 접속 / 해시에 데이터를 기록하는 것은 O (1)이다.

  12. ==============================

    12.난 당신이 MULTI / EXEC / 취소입니다 도움이 될 것 같아요. 거래의 100 % 해당하는 동안, 당신은 다른 업데이트에서 삭제를 분리 할 수 ​​있어야한다.

    난 당신이 MULTI / EXEC / 취소입니다 도움이 될 것 같아요. 거래의 100 % 해당하는 동안, 당신은 다른 업데이트에서 삭제를 분리 할 수 ​​있어야한다.

  13. ==============================

    13.참고하시기 바랍니다.

    참고하시기 바랍니다.

    어쩌면 당신은 단지 자본 문자를 수정해야합니다.

    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
    
  14. ==============================

    14.(프로덕션 서버에 대한 권장)와 xargs를하기보다는 --pipe KEYS보다는 SCAN을 사용하는 버전.

    (프로덕션 서버에 대한 권장)와 xargs를하기보다는 --pipe KEYS보다는 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
    
  15. ==============================

    15.그것은 FastoRedis에서 "제거 지점"기능을 통해 구현 간단합니다, 당신이 제거 할 지점을 선택합니다.

    그것은 FastoRedis에서 "제거 지점"기능을 통해 구현 간단합니다, 당신이 제거 할 지점을 선택합니다.

  16. ==============================

    16.이 명령을 사용하여 시도하십시오 :

    이 명령을 사용하여 시도하십시오 :

    redis-cli --raw keys "$PATTERN" | xargs redis-cli del
    
  17. ==============================

    17.이 질문에 직접 대답이 아니라 내 자신의 답변을 검색 할 때 내가 여기있어 이후로, 나는 여기를 공유 할 수 있습니다.

    이 질문에 직접 대답이 아니라 내 자신의 답변을 검색 할 때 내가 여기있어 이후로, 나는 여기를 공유 할 수 있습니다.

    당신이 수십 또는 당신이 일치 할 필요가 키 수억이있는 경우, 여기에 주어진 답변 레디 스 시간의 상당한 양의 (분?)에 대한 비 반응 원인이 될 것이며, 잠재적으로 확인 (때문에 메모리 소비의 뜻에 저장 배경 충돌 당신의 작업의 중간에있는 킥).

    다음과 같은 접근 방식은 명백하게 추악한,하지만 난 더 나은 하나를 찾을 수 없습니다. 자성은 주요 목표 레디 스를 주기적으로 업데이트하여 시간의 반응 100 %로이 경우에, 여기에 문제가 부족합니다. 당신이 데이터베이스 중 하나에 모든 키가 있다면 그것은 완벽하게 작동하고 당신은 어떤 패턴과 일치 할 필요가 없습니다,하지만 자연을 막고의 때문에 http://redis.io/commands/FLUSHDB을 사용할 수 없습니다.

    아이디어는 간단하다 http://redis.io/commands/SCAN 또는 http://redis.io/commands/RANDOMKEY 같은 루프를 사용 O의 실행 (1) 작업이 키를 얻을 수 있음을 경우, 검사를하는 스크립트를 작성 그들은 하나 패턴 (필요한 경우) 및 http://redis.io/commands/DEL 그들에게 하나와 일치.

    그것을 할 수있는 더 좋은 방법이 있다면, 내가 대답을 업데이 트됩니다, 알려 주시기 바랍니다.

    루비 randomkey 예는 구현, 갈퀴 작업, 같은의 비 차단 대체 등의 레디 스 - 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
    
  18. ==============================

    18.가난한 사람은 원자 질량 - 삭제입니까?

    가난한 사람은 원자 질량 - 삭제입니까?

    앞으로 몇 분처럼 - - 어쩌면 당신은 동일한 두 번째 EXPIREAT 그들 모두를 설정할 수 있고 그 때까지 기다려야하고 동시에 모든 "자폭"을 참조하십시오.

    하지만 난 것이 그 방법 원자 정말 모르겠습니다.

  19. ==============================

    19.나는 위에서 언급 한 방법의 대부분을 시도하지만 그들은 나를 위해 일을하지 않았다 일부 검색 후 나는 이러한 점을 발견 :

    나는 위에서 언급 한 방법의 대부분을 시도하지만 그들은 나를 위해 일을하지 않았다 일부 검색 후 나는 이러한 점을 발견 :

    그래서 패턴에 의해 삭제 키에이 코드를 사용 :

     redis-cli -n 2 --scan --pattern '[your pattern]' | xargs redis-cli -n 2 unlink 
    
  20. ==============================

    20.지금의 광고, 당신은 레디 스 클라이언트를 사용하여 먼저 SCAN (지원 패턴 매칭) 및 각 키를 개별적으로 다음 DEL을 수행 할 수 있습니다.

    지금의 광고, 당신은 레디 스 클라이언트를 사용하여 먼저 SCAN (지원 패턴 매칭) 및 각 키를 개별적으로 다음 DEL을 수행 할 수 있습니다.

    그러나 공식 레디 스에 대한 문제는 여기에 델 - 패턴과 일치하는을 만들기 위해 당신이 유용한 경우 약간의 사랑을 보여 가서이 GitHub의입니다!

  21. ==============================

    21.나는 몇 가지 도구를 가지고 또는 루아 식을 실행에 관련된 모든 대답을 지원합니다.

    나는 몇 가지 도구를 가지고 또는 루아 식을 실행에 관련된 모든 대답을 지원합니다.

    내 옆에서 한 번 더 옵션 :

    우리의 생산 및 프리 프로덕션 데이터베이스에서 키의 수천이있다. 우리는 (일부 마스크에 의해) 일부 키를 삭제해야 할 시간 시간 등 물론 어떤 기준에 의해 수정, 특히 샤딩 (각 물리적 512 논리적 DBS)을 갖는, CLI에서 수동으로 할 수있는 방법은 없습니다.

    이를 위해 나는이 모든 작업을 수행 자바 클라이언트 도구를 작성합니다. 키의 경우, 유틸리티, 하나의 클래스 만이 매우 간단 할 수 삭제 :

    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();
        }
    
    }
    
  22. ==============================

    22.다음 명령은 나를 위해 일했다.

    다음 명령은 나를 위해 일했다.

    redis-cli -h redis_host_url KEYS "*abcd*" | xargs redis-cli -h redis_host_url DEL
    
  23. ==============================

    23.키 특수 문자가 포함 된 경우 다른 답변이 작동하지 않을 수 있습니다 - 예를 들어 가이드 $ CLASSMETADATA] [1]. 따옴표로 각 키를 포장하는 것은 제대로 삭제 얻을 보장합니다 :

    키 특수 문자가 포함 된 경우 다른 답변이 작동하지 않을 수 있습니다 - 예를 들어 가이드 $ CLASSMETADATA] [1]. 따옴표로 각 키를 포장하는 것은 제대로 삭제 얻을 보장합니다 :

    redis-cli --scan --pattern sf_* | awk '{print $1}' | sed "s/^/'/;s/$/'/" | xargs redis-cli del
    
  24. ==============================

    24.봄 RedisTemplate 자체가 기능을 제공합니다. 최신 버전의 RedissonClient는 "deleteByPattern"기능을 사용 중지했다.

    봄 RedisTemplate 자체가 기능을 제공합니다. 최신 버전의 RedissonClient는 "deleteByPattern"기능을 사용 중지했다.

    Set<String> keys = redisTemplate.keys("geotag|*");
    redisTemplate.delete(keys);
    
  25. from https://stackoverflow.com/questions/4006324/how-to-atomically-delete-keys-matching-a-pattern-using-redis by cc-by-sa and MIT license