どのように原子的に削除キーをマッチングパターンを用いRedis

StackOverflow https://stackoverflow.com/questions/4006324

  •  25-09-2019
  •  | 
  •  

質問

私のRedis DBいて prefix:<numeric_id> ハッシュ.

たいパージして原子.いいなあのロック機構?

役に立ちましたか?

解決

のRedis 2.6.0以降では、アトミックに実行するのluaスクリプトを実行することができます。私は1つを書いたことがありませんが、私はそれは次のようになりますだと思います。

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

EVALドキュメントを参照してください。

他のヒント

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 から古い値を安全に取得し、古いキーを削除できます。

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

キキトの提案どおり。

免責事項:次の解決策 しません アトミック性を提供します。

v2.8 からは、 本当に を使用したい スキャン 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] キー は、DoS を引き起こす可能性がある危険なコマンドです。以下はドキュメント ページからの引用です。

警告: KEYS は、運用環境でのみ使用する必要があるコマンドとして細心の注意を払って検討してください。大規模なデータベースに対して実行すると、パフォーマンスが低下する可能性があります。このコマンドは、デバッグや、キースペースのレイアウトの変更などの特殊な操作を目的としています。通常のアプリケーション コードでは KEYS を使用しないでください。キースペースのサブセットでキーを検索する方法を探している場合は、セットの使用を検討してください。

アップデート: 同じ基本効果のワンライナー -

$ redis-cli --scan --pattern "*:foo:bar:*" | xargs -L 100 redis-cli DEL
トラブル他の回答を解析したし、人のために

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

独自のパターンでkey:*:patternを交換し、redis-cliにこれを入力すると、あなたが行ってもいいです。

クレジットliscoから: http://redis.io/commands/delする

私はRedisの中でコマンドの下に使用しています3.2.8。

redis-cli KEYS *YOUR_KEY_PREFIX* | xargs redis-cli DEL
https://redis.io/commands/ - :

現在のページから、キーパターンの検索に関連するより多くの助けを得ることができますキーはを。以下のようなあなたの要件ごとに、あなたの便利なglobスタイルのパターンを使用しての *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);
            }
        }

ありがとう:)

@ mcdizleのソリューションは、それが一つのエントリに対してのみ機能動作しません。

同じ接頭辞を持つすべてのキーのためのこの1つの作品

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

注:あなたのキーで 'プレフィックス' を置換すべき接頭辞...

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

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'

元- 'xyz_category_fpc' ここ xyz です サイト名, 、これらのキーは電子商取引サイトの製品とカテゴリに関連しており、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-cli の場合:

  1. フラッシュDB - 接続の現在のデータベースからデータを削除します。
  2. フラッシュホール - すべてのデータベースからデータを削除します。

例:- シェル内:

redis-cli flushall
redis-cli flushdb

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

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

@ itamarの答えは素晴らしいですが、応答の解析は、ESP、私のために働いていませんでした。何のキーが存在しない場合には所定の走査で見つかりました。おそらく簡単な解決策、直接コンソールから:

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

これはまた、生産のキーに好ましいSCANを使用するが、アトミックではない。

私は同じ問題を抱えていました。私は形式のユーザーのセッションデータを格納します:

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

ですから、各エントリは別々のキーと値のペアでした。セッションが破棄されたとき、私は、パターンsession:sessionid:*でキーを削除して、すべてのセッションデータを削除したい - しかし、Redisのは、このような機能を持っていません。

。 私が何をしたか

:A ハッシュの内のストアのセッションデータを。私はちょうどsession:sessionidのハッシュIDを持つハッシュを作成し、私はkey-xkey-y、そのハッシュでkey-z(順序は私には問題ではありませんでした)、私は、ハッシュはもう私はちょうどDEL session:sessionidおよびそれに関連するすべてのデータを行うことの必要性をいけない場合を押しますハッシュIDがなくなっています。 DELは原子及びアクセスデータ/ハッシュにデータを書き込んでいることO(1)である。

ご参考までに。

  • bash のみを使用し、 redis-cli
  • 使用していない keys (これは scan)
  • でうまく機能します クラスタモード
  • 原子的ではない

大文字のみを変更する必要があるかもしれません。

スキャンマッチ.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

クリア-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

私はあなたが MULTI / EXEC / DISCARD にある役立つかもしれないものだと思います。 、あなたをに取引のない 100%に相当しながら、他の更新からの削除を単離することができる必要があります。

これは、単純な「削除ブランチ」 FastoRedis の中の機能、削除するだけで選択ブランチを介して実行されます。

このコマンドを使用してみてください。

redis-cli --raw keys "$PATTERN" | xargs redis-cli del

SCANではなくKEYS(本番サーバに推奨される)と--pipeではなく、xargsのを使用してバージョン。

それは、より効率的だとあなたの鍵を試してみると自分の殻という引用符や他の特殊文字が含まれていると解釈したときに動作しますので、

私は、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 でブロックです。

アイデアはシンプルです:書く上で動作するスクリプトループを使O(1)操作のように http://redis.io/commands/SCAN または http://redis.io/commands/RANDOMKEY をキーチェック合しているかのパターン(請求-お問い合わせはこちら) http://redis.io/commands/DEL しています。

がある場合と良いので、ぜひ<url>までご連絡ください、更新の答えです。

例実装randomkey Rubyで、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

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

  • Redis 上に複数のデータベースがある場合は、次を使用してデータベースを決定する必要があります。 -n [number]
  • いくつかのキーがある場合は使用します del ただし、数千または数百万のキーがある場合は、次の方法を使用することをお勧めします。 unlink なぜなら リンク解除は非ブロッキングです del がブロックしている間、詳細については、このページをご覧ください。 リンク解除と削除
  • また keys del のようなものでブロックされています

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

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

私はいくつかのツールを持つか、Luaの式を実行に関連するすべての答えをサポートしています。

私の側からもう一つのオプションます:

私たちの生産やプリプロダクションのデータベースでは、キーの数千人があります。我々は(いくつかのマスクで)いくつかのキーを削除する必要がある時には、もちろん、などいくつかの基準によって変更時間は、CLIから手動でそれを行うための方法は、特に持つ(各物理で512論理DBS)をシャーディング、ありません。

このすべての作業を行い、この目的のI書き込み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();
    }

}
コマンド以下は

は私のために働いています。

redis-cli -h redis_host_url KEYS "*abcd*" | xargs redis-cli -h redis_host_url DEL
今、あなたが個別に各キーをRedisのクライアントを使用し、最初のSCAN(サポートパターンマッチング)を行い、その後、DELことができます。

広告 しかし、パター・マッチング・デルここを作成するために、公式のRedisのgithubの上の問題がありますあなたはそれが役に立つ場合に、それにいくつかの愛を示すGO!

貧乏人の原子質量-削除しますか?

将来的には、数分のような - - 多分あなたは同じ第二のEXPIREATためにそれらすべてを設定することができます。その後、その時まで待つと同時に、それらをすべて「自己破壊」を参照してください。

が、私は本当にないですしてくださいどのように原子それは次のようになります。

春RedisTemplate自体が機能を提供します。 RedissonClientは最新バージョンでは「deleteByPattern」機能が非推奨になりました。

Set<String> keys = redisTemplate.keys("geotag|*");
redisTemplate.delete(keys);
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top