私のRedisDBには、いくつかのprefix:<numeric_id>
ハッシュがあります。
時々私はそれらをすべてアトミックにパージしたいです。分散ロックメカニズムを使用せずにこれを行うにはどうすればよいですか?
私のRedisDBには、いくつかのprefix:<numeric_id>
ハッシュがあります。
時々私はそれらをすべてアトミックにパージしたいです。分散ロックメカニズムを使用せずにこれを行うにはどうすればよいですか?
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から古い値を安全に取得し、古いキーを削除できます。
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のドキュメントを参照してください。
これは、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]の代わりに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
他の答えを解析するのに苦労していた人のために:
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
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);
}
}
ありがとうございました :)
このコマンドを使用して、キーを削除することもできます。-
あなたのredisには多くの種類のキーがあるとしましょう-
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を使用する場合:
例:-シェル内:
redis-cli flushall
redis-cli flushdb
@mcdizleのソリューションは機能していません。これは、1つのエントリに対してのみ機能します。
これは、同じプレフィックスを持つすべてのキーで機能します
EVAL "for i, name in ipairs(redis.call('KEYS', ARGV[1])) do redis.call('DEL', name); end" 0 prefix*
注:「prefix」をキープレフィックスに置き換える必要があります...
キーの名前にスペースがある場合は、bashでこれを使用できます。
redis-cli keys "pattern: *" | xargs -L1 -I '$' echo '"$"' | xargs redis-cli del
@itamarの答えは素晴らしいですが、返信の解析は私にとってはうまくいきませんでした。特定のスキャンでキーが見つからない場合。コンソールから直接、おそらくより単純な解決策:
redis-cli -h HOST -p PORT --scan --pattern "prefix:*" | xargs -n 100 redis-cli DEL
これもSCANを使用します。これは、本番環境ではKEYSよりも望ましいですが、アトミックではありません。
たとえば、キーに特別な文字が含まれている場合、他の回答が機能しない可能性がありGuide$CLASSMETADATA][1]
ます。各キーを引用符で囲むと、適切に削除されます。
redis-cli --scan --pattern sf_* | awk '{print $1}' | sed "s/^/'/;s/$/'/" | xargs 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
プッシュします(順序は関係ありません)。そのハッシュが不要になった場合は、を実行するだけで、そのハッシュIDに関連付けられているすべてのデータが失われます。はアトミックであり、データへのアクセス/ハッシュへのデータの書き込みはO(1)です。key-x
key-y
key-z
DEL session:sessionid
DEL
// TODO
あなたはそれが正しく機能していないようなRedisコマンドが時々意味をなさないコマンドだと思いDEL
、これの救助に来ます
redis-cli KEYS "*" | xargs -i redis-cli EXPIRE {} 1
それはライフハックです
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
私はあなたを助けるかもしれないのは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
このコマンドを使用して試してください:
redis-cli --raw keys "$PATTERN" | xargs redis-cli del
これは質問に対する直接の答えではありませんが、私は自分の答えを探すときにここに来たので、ここでこれを共有します。
一致させる必要のあるキーが数千または数億ある場合、ここでの回答により、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
上記のほとんどの方法を試しましたが、うまくいきませんでした。いくつか検索したところ、次の点が見つかりました。
-n [number]
del
千または数百万のキーがある場合は、delがブロックしている間はリンク解除が非ブロックであるため、使用することをunlink
お勧めします。詳細については、このページにアクセスしてください。keys
、デルのようであり、ブロックしていますそのため、このコードを使用して、パターンごとにキーを削除しました。
redis-cli -n 2 --scan --pattern '[your pattern]' | xargs redis-cli -n 2 unlink
以下のコマンドは私のために働いた。
redis-cli -h redis_host_url KEYS "*abcd*" | xargs redis-cli -h redis_host_url DEL
私はこれをEVALコマンドの最も単純な変形で成功させました:
EVAL "return redis.call('del', unpack(redis.call('keys', my_pattern_here*)))" 0
my_pattern_here
ここで私は自分の価値観に置き換えました。
この答えに追加する:
最初の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_*
これは私にとってはうまくいきましたが、アトミックではないかもしれません:
redis-cli keys "stats.*" | cut -d ' ' -f2 | xargs -d '\n' redis-cli DEL
貧乏人の原子量-削除?
たぶん、それらすべてを同じ秒でEXPIREATに設定し(将来の数分など)、その時間まで待って、それらすべてが同時に「自己破壊」するのを見ることができます。
しかし、それがどれほどアトミックになるかはよくわかりません。
ツールの使用や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();
}
}
今のところ、redisクライアントを使用して、最初にSCAN(パターンマッチングをサポート)を実行してから、各キーを個別にDELすることができます。
ただし、公式のredis githubには、ここでパターンマッチングデルを作成するための問題があります。便利な場合は、愛を示してください。
キー名にスペースがある場合、これはMacOSで機能します
redis-cli --scan --pattern "myprefix:*" | tr \\n \\0 | xargs -0 redis-cli unlink
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
Windows環境を使用している場合は、次の手順に従ってください。確実に機能します。
ここからGOWをダウンロードします-https ://github.com/bmatzelle/gow/wiki(xargsコマンドはWindowsでは機能しないため)
Windows用のredis-cliをダウンロードします(詳細な説明はこちら-https: //medium.com/@binary10111010/redis-cli-installation-on-windows-684fb6b6ac6b)
cmdを実行し、redis-cliが保存されているディレクトリを開きます(例:D:\ Redis \ Redis-x64-3.2.100)
「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
これは、xargsマジックを使用せずに頭に浮かぶ最も簡単な方法です
純粋なbash!
redis-cli DEL $(redis-cli KEYS *pattern*)
SpringRedisTemplate自体が機能を提供します。最新バージョンのRedissonClientは、「deleteByPattern」機能を廃止しました。
Set<String> keys = redisTemplate.keys("geotag|*");
redisTemplate.delete(keys);