677

私のRedisDBには、いくつかのprefix:<numeric_id>ハッシュがあります。

時々私はそれらをすべてアトミックにパージしたいです。分散ロックメカニズムを使用せずにこれを行うにはどうすればよいですか?

4

31 に答える 31

796

bashで実行:

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

アップデート

わかった。この方法についてはどうでしょうか。現在の追加の増分プレフィックスを保存し、それをすべてのキーに追加します。例えば:

次のような値があります。

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

データをパージする必要がある場合は、最初にprefix_actuallを変更して(たとえば、prefix_prefix_actuall = 3に設定)、アプリケーションが新しいデータをキーprefix:3:1およびprefix:3:2に書き込みます。次に、prefix:2:1とprefix:2:2から古い値を安全に取得し、古いキーを削除できます。

于 2010-10-23T23:31:15.880 に答える
471

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のドキュメントを参照してください。

于 2013-06-06T23:47:53.097 に答える
84

これは、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

キキトが提案したように。

于 2013-06-10T04:20:43.760 に答える
73

免責事項:次のソリューションは原子性を提供しません。

v2.8以降では、KEYS[1]の代わりにSCANコマンドを使用する必要があります。次の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は、実稼働環境でのみ細心の注意を払って使用する必要があるコマンドと見なしてください。大規模なデータベースに対して実行すると、パフォーマンスが低下する可能性があります。このコマンドは、キースペースレイアウトの変更など、デバッグおよび特別な操作を目的としています。通常のアプリケーションコードではKEYSを使用しないでください。キースペースのサブセットでキーを見つける方法を探している場合は、セットの使用を検討してください。

更新:同じ基本的な効果のためのワンライナー-

$ redis-cli --scan --pattern "*:foo:bar:*" | xargs -L 100 redis-cli DEL
于 2014-04-30T22:26:54.790 に答える
55

他の答えを解析するのに苦労していた人のために:

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

于 2014-03-19T15:32:24.963 に答える
42

redis3.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);
            }
        }

ありがとうございました :)

于 2017-05-08T07:33:48.607 に答える
31

このコマンドを使用して、キーを削除することもできます。-

あなたのredisには多くの種類のキーがあるとしましょう-

  1. 'xyz_category_fpc_12'
  2. 'xyz_category_fpc_245'
  3. 'xyz_category_fpc_321'
  4. 'xyz_product_fpc_876'
  5. 'xyz_product_fpc_302'
  6. 'xyz_product_fpc_01232'

Ex -'xyz_category_fpc 'ここで、 xyzサイト名であり、これらのキーはEコマースサイトの製品とカテゴリに関連しており、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 」を使用します。

Redisですべてを削除する場合は、次のコマンドに従います-

redis-cliを使用する場合:

  1. FLUSHDB-接続のCURRENTデータベースからデータを削除します。
  2. FLUSHALL-すべてのデータベースからデータを削除します。

例:-シェル内:

redis-cli flushall
redis-cli flushdb
于 2017-01-12T18:31:11.997 に答える
26

@mcdizleのソリューションは機能していません。これは、1つのエントリに対してのみ機能します。

これは、同じプレフィックスを持つすべてのキーで機能します

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

注:「prefix」をキープレフィックスに置き換える必要があります...

于 2014-12-19T07:20:32.253 に答える
15

キーの名前にスペースがある場合は、bashでこれを使用できます。

redis-cli keys "pattern: *" | xargs -L1 -I '$' echo '"$"' | xargs redis-cli del
于 2015-03-04T23:48:41.813 に答える
13

@itamarの答えは素晴らしいですが、返信の解析は私にとってはうまくいきませんでした。特定のスキャンでキーが見つからない場合。コンソールから直接、おそらくより単純な解決策:

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

これもSCANを使用します。これは、本番環境ではKEYSよりも望ましいですが、アトミックではありません。

于 2015-06-23T02:18:55.200 に答える
13

たとえば、キーに特別な文字が含まれている場合、他の回答が機能しない可能性がありGuide$CLASSMETADATA][1]ます。各キーを引用符で囲むと、適切に削除されます。

redis-cli --scan --pattern sf_* | awk '{print $1}' | sed "s/^/'/;s/$/'/" | xargs redis-cli del
于 2019-11-15T14:45:58.660 に答える
10

私はちょうど同じ問題を抱えていました。ユーザーのセッションデータを次の形式で保存しました。

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プッシュします(順序は関係ありません)。そのハッシュが不要になった場合は、を実行するだけで、そのハッシュIDに関連付けられているすべてのデータが失われます。はアトミックであり、データへのアクセス/ハッシュへのデータの書き込みはO(1)です。key-xkey-ykey-zDEL session:sessionidDEL

于 2010-12-18T19:06:29.430 に答える
8

// TODO

あなたはそれが正しく機能していないようなRedisコマンドが時々意味をなさないコマンドだと思いDEL、これの救助に来ます

redis-cli KEYS "*" | xargs -i redis-cli EXPIRE {} 1それはライフハックです

于 2020-11-18T09:22:12.420 に答える
6

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
于 2017-06-26T01:23:59.280 に答える
5

私はあなたを助けるかもしれないのはMULTI/EXEC/DISCARDだと思います。トランザクションと100%同等ではありませんが、削除を他の更新から分離できるはずです。

于 2010-10-24T08:51:05.663 に答える
5

ご参考までに。

  • bashと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
于 2017-05-08T07:08:03.703 に答える
4

このコマンドを使用して試してください:

redis-cli --raw keys "$PATTERN" | xargs redis-cli del
于 2018-11-29T14:02:13.550 に答える
3

これは質問に対する直接の答えではありませんが、私は自分の答えを探すときにここに来たので、ここでこれを共有します。

一致させる必要のあるキーが数千または数億ある場合、ここでの回答により、Redisはかなりの時間(分?)応答しなくなり、メモリ消費のためにクラッシュする可能性があります(確かに、バックグラウンド保存は操作の途中でキックインします)。

次のアプローチは間違いなく醜いですが、私はより良いものを見つけられませんでした。Atomicityはここでは問題外です。この場合の主な目標は、Redisを常に稼働させて応答性を維持することです。いずれかのデータベースにすべてのキーがあり、どのパターンにも一致する必要がない場合は完全に機能しますが、ブロックの性質があるため、http://redis.io/commands/FLUSHDBを使用できません。

アイデアは単純です。ループで実行され、http ://redis.io/commands/SCANやhttp://redis.io/commands/RANDOMKEYなどのO(1)操作を使用してキーを取得し、キーがあるかどうかを確認するスクリプトを記述します。パターンを一致させ(必要な場合)、http://redis.io/commands/DELを1つずつ実行します。

それを行うためのより良い方法があれば、私に知らせてください、私は答えを更新します。

Rubyでのrandomkeyを使用した実装例、rakeタスクとして、次のようなもののノンブロッキング代替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
于 2016-02-22T14:01:45.447 に答える
3

上記のほとんどの方法を試しましたが、うまくいきませんでした。いくつか検索したところ、次の点が見つかりました。

  • redisに複数のデータベースがある場合は、を使用してデータベースを決定する必要があります-n [number]
  • いくつかのキーを使用しているが、数del千または数百万のキーがある場合は、delがブロックしている間はリンク解除が非ブロックであるため、使用することunlinkお勧めします。詳細については、このページにアクセスしてください。
  • またkeys、デルのようであり、ブロックしています

そのため、このコードを使用して、パターンごとにキーを削除しました。

 redis-cli -n 2 --scan --pattern '[your pattern]' | xargs redis-cli -n 2 unlink 
于 2019-07-11T04:13:33.163 に答える
2

以下のコマンドは私のために働いた。

redis-cli -h redis_host_url KEYS "*abcd*" | xargs redis-cli -h redis_host_url DEL
于 2019-09-12T08:28:05.770 に答える
2

私はこれをEVALコマンドの最も単純な変形で成功させました:

EVAL "return redis.call('del', unpack(redis.call('keys', my_pattern_here*)))" 0

my_pattern_hereここで私は自分の価値観に置き換えました。

于 2021-05-19T07:39:37.980 に答える
2

この答えに追加する:

最初の1000個のキーを見つけるには:

EVAL "return redis.call('scan', 0, 'COUNT', 1000, 'MATCH', ARGV[1])" 0 find_me_*

それらを削除するには:

EVAL "return redis.call('del', unpack(redis.call('SCAN', 0, 'COUNT', 1000, 'MATCH', ARGV[1])[2]))" 0 delete_me_*
于 2021-10-25T16:45:58.663 に答える
1

これは私にとってはうまくいきましたが、アトミックではないかもしれません:

redis-cli keys "stats.*" | cut -d ' ' -f2 | xargs -d '\n' redis-cli DEL
于 2021-05-10T16:40:14.130 に答える
0

貧乏人の原子量-削除?

たぶん、それらすべてを同じ秒でEXPIREATに設定し(将来の数分など)、その時間まで待って、それらすべてが同時に「自己破壊」するのを見ることができます。

しかし、それがどれほどアトミックになるかはよくわかりません。

于 2014-03-13T16:28:31.453 に答える
0

ツールの使用やLua式の実行に関連するすべての回答をサポートします。

私の側からのもう1つのオプション:

本番データベースと本番前データベースには、何千ものキーがあります。時々、いくつかのキーを(いくつかのマスクで)削除したり、いくつかの基準で変更したりする必要があります。もちろん、特にシャーディング(各物理に512論理データベース)がある場合、CLIから手動で削除する方法はありません。

この目的のために、私はこのすべての作業を行うJavaクライアントツールを作成します。キーを削除する場合、ユーティリティは非常に単純で、クラスは1つだけです。

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

}
于 2016-09-01T18:52:01.733 に答える
0

今のところ、redisクライアントを使用して、最初にSCAN(パターンマッチングをサポート)を実行してから、各キーを個別にDELすることができます。

ただし、公式のredis githubには、ここでパターンマッチングデルを作成するための問題があります。便利な場合は、愛を示してください。

于 2019-09-12T14:14:25.470 に答える
0

キー名にスペースがある場合、これはMacOSで機能します

redis-cli --scan --pattern "myprefix:*" | tr \\n \\0 | xargs -0 redis-cli unlink
于 2021-03-09T15:45:16.167 に答える
0

4未満のRedisバージョンを使用している場合は、試してみてください

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
于 2021-12-08T05:06:49.353 に答える
-1

Windows環境を使用している場合は、次の手順に従ってください。確実に機能します。

  1. ここからGOWをダウンロードします-https ://github.com/bmatzelle/gow/wiki(xargsコマンドはWindowsでは機能しないため)

  2. Windows用のredis-cliをダウンロードします(詳細な説明はこちら-https: //medium.com/@binary10111010/redis-cli-installation-on-windows-684fb6b6ac6b

  3. cmdを実行し、redis-cliが保存されているディレクトリを開きます(例:D:\ Redis \ Redis-x64-3.2.100)

  4. 「Global:ProviderInfo」で始まるすべてのキーを削除する場合は、このクエリを実行します(これは単なる例であるため、太字のパラメータ(ホスト、ポート、パスワード、キー)を変更し、自分のパラメータを書き込む必要があります)。

    redis-cli -h redis.test.com -p 6379 -a redispassword --raw keys " Global:ProviderInfo *" | xargs redis-cli -h redis.test.com -p 6379 -a redispassword del

于 2020-10-27T11:39:09.113 に答える
-1

これは、xargsマジックを使用せずに頭に浮かぶ最も簡単な方法です

純粋なbash!

redis-cli DEL $(redis-cli KEYS *pattern*)
于 2022-02-07T15:17:27.513 に答える
-3

SpringRedisTemplate自体が機能を提供します。最新バージョンのRedissonClientは、「deleteByPattern」機能を廃止しました。

Set<String> keys = redisTemplate.keys("geotag|*");
redisTemplate.delete(keys);
于 2015-11-30T10:29:28.577 に答える