Redis DB'mde birkaç prefix:<numeric_id>
karma var.
Bazen hepsini atomik olarak temizlemek istiyorum. Bazı dağıtılmış kilitleme mekanizmaları kullanmadan bunu nasıl yapabilirim?
Redis DB'mde birkaç prefix:<numeric_id>
karma var.
Bazen hepsini atomik olarak temizlemek istiyorum. Bazı dağıtılmış kilitleme mekanizmaları kullanmadan bunu nasıl yapabilirim?
Yanıtlar:
Redis 2.6.0 ile başlayarak, atomik olarak çalışan lua komut dosyalarını çalıştırabilirsiniz. Hiç yazmadım ama bence böyle bir şey olurdu
EVAL "return redis.call('del', unpack(redis.call('keys', ARGV[1])))" 0 prefix:[YOUR_PREFIX e.g delete_me_*]
Uyarı : Redis belgesinde belirtildiği gibi, performans önemli olduğundan
keys
komut, üretimdeki düzenli işlemler için kullanılmamalıdır, bu komut hata ayıklama ve özel işlemler için tasarlanmıştır. daha fazla oku
EVAL belgelerine bakın .
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:*
temel bir işlem gibi görünüyor : /
EVAL "return redis.call('del', 'defaultKey', unpack(redis.call('keys', ARGV[1])))" 0 prefix:*
Bash'da yürüt:
redis-cli KEYS "prefix:*" | xargs redis-cli DEL
GÜNCELLEME
Tamam anladım. Peki bu şekilde: geçerli ek artımlı öneki saklayın ve tüm anahtarlarınıza ekleyin. Örneğin:
Bunun gibi değerleriniz var:
prefix_prefix_actuall = 2
prefix:2:1 = 4
prefix:2:2 = 10
Verileri temizlemeniz gerektiğinde, önce önek_etkiallerini değiştirirsiniz (örneğin, önek_prefix_actuall = 3'ü ayarlarsınız), böylece uygulamanız anahtar önekine 3: 1 ve önek: 3: 2'ye yeni veriler yazar. Ardından, eski değerleri önek: 2: 1 ve önek: 2: 2'den güvenle alabilir ve eski anahtarları temizleyebilirsiniz.
redis-cli KEYS "prefix:*" | xargs --delim='\n' redis-cli DEL
redis-cli -n 3 KEYS "prefix:*" | xargs redis-cli -n 3 DEL
İşte Lua'da uygulanan bir joker karakter silinmesinin tamamen çalışan ve atomik bir versiyonu. Çok daha az ağ ileri geri nedeniyle xargs sürümünden çok daha hızlı çalışır ve tamamen atomiktir, bitene kadar yeniden isteklere karşı diğer istekleri engeller. Redis 2.6.0 veya üzerindeki anahtarları atomik olarak silmek istiyorsanız, bu kesinlikle gitmenin yoludur:
redis-cli -n [some_db] -h [some_host_name] EVAL "return redis.call('DEL', unpack(redis.call('KEYS', ARGV[1] .. '*')))" 0 prefix:
Bu, @ mcdizzle'ın bu soruya cevabındaki fikrinin çalışan bir versiyonudur. Fikir için kredi% 100 ona gider.
DÜZENLEME: Aşağıdaki Kikito'nun yorumuna göre, Redis sunucunuzda boş bellekten daha fazla anahtarınız varsa, "paketini açmak için çok fazla öğe" hatasıyla karşılaşırsınız . Bu durumda şunları yapın:
for _,k in ipairs(redis.call('keys', ARGV[1])) do
redis.call('del', k)
end
Kikito'nun önerdiği gibi.
for _,k in ipairs(redis.call('keys', KEYS[1])) do redis.call('del', k) end
unpack
bir tabloyu "bağımsız değişkenler listesindeki" dönüştürür (diğer diller buna denir explode
), ancak maksimum sayı sistem hafızasına bağlı değildir; sabit içinde lua sabitlenir LUAI_MAXSTACK
. Lua 5.1 ve LuaJIT'de 8000 ve Lua 5.2'de 100000'dir. For loop seçeneği IMO önerilir.
EVAL
üzerinde çalışacağı anahtarları önceden belirtmediği için anlambilimini ihlal edecektir. Tek bir örnek üzerinde çalışması gerekir, ancak Redis Kümesi ile çalışmasını beklemez.
Yasal Uyarı: Aşağıdaki çözüm değildir atomicity sağlarlar.
V2.8 ile başlayarak Eğer gerçekten kullanmak istediğiniz TARAMA ANAHTARLIĞI [1] yerine komutu. Aşağıdaki Bash betiği anahtarların desene göre silinmesini gösterir:
#!/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 , potansiyel olarak DoS ile sonuçlanabilecek tehlikeli bir komuttur. Aşağıda, dokümantasyon sayfasından bir alıntı yer almaktadır:
Uyarı: KEYS'i yalnızca çok dikkatli olan üretim ortamlarında kullanılması gereken bir komut olarak düşünün. Büyük veritabanlarına karşı yürütüldüğünde performansı bozabilir. Bu komut hata ayıklama ve anahtar boşluk düzeninizi değiştirme gibi özel işlemler için tasarlanmıştır. Normal uygulama kodunuzda KEYS kullanmayın. Anahtar alanınızın bir alt kümesindeki anahtarları bulmanın bir yolunu arıyorsanız, kümeleri kullanmayı düşünün.
GÜNCELLEME: aynı temel etki için bir astar -
$ redis-cli --scan --pattern "*:foo:bar:*" | xargs -L 100 redis-cli DEL
-n 1
her redis-cli
çağırma eklemek zorunda kaldı :redis-cli -n 1 --scan --pattern "*:foo:bar:*" | xargs -L 100 redis-cli -n 1 DEL
Diğer cevapları ayrıştırmada sorun yaşayanlar için:
eval "for _,k in ipairs(redis.call('keys','key:*:pattern')) do redis.call('del',k) end" 0
key:*:pattern
Kendi deseninizle değiştirin redis-cli
ve bunu girin ve gitmekte fayda var.
Kredi lisco: http://redis.io/commands/del
Redis 3.2.8'de aşağıdaki komutu kullanıyorum
redis-cli KEYS *YOUR_KEY_PREFIX* | xargs redis-cli DEL
Anahtar deseni aramasıyla ilgili daha fazla yardımı buradan edinebilirsiniz: - https://redis.io/commands/keys . Uygun glob tarzı deseninizi *YOUR_KEY_PREFIX*
veya benzeri YOUR_KEY_PREFIX??
herhangi bir gereksiniminize göre kullanın .
Ve eğer herhangi biriniz Redis PHP kütüphanesini aşağıdaki fonksiyonlardan daha entegre ederseniz size yardımcı olacaktır.
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);
}
}
Teşekkür ederim :)
@ mcdizle'nin çözümü çalışmıyor, sadece bir giriş için çalışıyor.
Bu, aynı önekle tüm anahtarlar için çalışır
EVAL "for i, name in ipairs(redis.call('KEYS', ARGV[1])) do redis.call('DEL', name); end" 0 prefix*
Not: "Önek" i anahtar önekinizle değiştirmeniz gerekir ...
Bu komutu tuşları silmek için de kullanabilirsiniz: -
Yeniden düşünmenizde birçok anahtar türü olduğunu varsayalım.
Ex- ' xyz_category_fpc ' burada xyz bir site adıdır ve bu anahtarlar bir E-Ticaret sitesinin ürünleri ve kategorileri ile ilgilidir ve FPC tarafından oluşturulur.
Bu komutu aşağıdaki gibi kullanırsanız
redis-cli --scan --pattern 'key*' | xargs redis-cli del
VEYA
redis-cli --scan --pattern 'xyz_category_fpc*' | xargs redis-cli del
' Xyz_category_fpc ' gibi tüm tuşları siler (1, 2 ve 3 anahtarlarını sil). Diğer 4, 5 ve 6 sayı tuşlarını silmek için yukarıdaki komutta ' xyz_product_fpc ' kullanın.
İsterseniz her şey sil yılında REDIS , daha sonra bu Commands izleyin
Redis-cli ile:
Örneğin: - kabuğunuzda:
redis-cli flushall
redis-cli flushdb
redis-cli del
atomik değildir.
@ itamar'ın cevabı harika, ama cevabın ayrıştırılması benim için çalışmıyor, esp. belirli bir taramada anahtar bulunamaması durumunda. Doğrudan konsoldan daha basit bir çözüm:
redis-cli -h HOST -p PORT --scan --pattern "prefix:*" | xargs -n 100 redis-cli DEL
Bu aynı zamanda üretimde KEYS'e tercih edilen ancak atomik olmayan SCAN kullanır.
Ben de aynı problemi yaşadım. Bir kullanıcının oturum verilerini şu biçimde depoladım:
session:sessionid:key-x - value of x
session:sessionid:key-y - value of y
session:sessionid:key-z - value of z
Yani, her bir giriş ayrı bir anahtar / değer çiftiydi. Oturum yok edildiğinde, kalıplı anahtarları silerek tüm oturum verilerini kaldırmak istedim session:sessionid:*
- ancak redis'in böyle bir işlevi yok.
Ne yaptım: oturum verilerini bir karma içinde saklayın . Sadece bir karma kimliğe sahip bir karma oluşturmak session:sessionid
ve sonra itin key-x
, key-y
, key-z
bu karmaşanın içinde (sipariş bana önemli değildi) ve karma artık sadece bir yapmak bu ihtiyacı yoksa DEL session:sessionid
ve bu karma kimliği ile ilişkili tüm veriler de silinir. DEL
atomiktir ve verilere erişmek / hash'e veri yazmak O (1) 'dir.
Sanırım size yardımcı olabilecek şey MULTI / EXEC / DISCARD . İşlemlerin% 100'üne eşdeğer olmasa da , silme işlemlerini diğer güncelleştirmelerden ayırabilmeniz gerekir.
Bilginize.
redis-cli
keys
(bu kullanır scan
)Belki sadece büyük harfleri değiştirmeniz gerekir.
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 isteminde çalıştır
$ ./clear-redis-key.sh key_head_pattern
Anahtarınız özel karakter içeriyorsa diğer yanıtlar çalışmayabilir Guide$CLASSMETADATA][1]
(örneğin. Her anahtarı tırnak içine almak, düzgün bir şekilde silinmelerini sağlayacaktır:
redis-cli --scan --pattern sf_* | awk '{print $1}' | sed "s/^/'/;s/$/'/" | xargs redis-cli del
KEYS yerine (üretim sunucuları için önerildiği gibi) ve --pipe
xargs yerine SCAN kullanan bir sürüm .
Boruları xargs'a tercih ediyorum çünkü daha verimli ve anahtarlarınız tırnak işaretleri veya kabuğunuzun denemek ve yorumlamak için başka özel karakterler içerdiğinde çalışıyor. Bu örnekteki normal ifade ikamesi, anahtarı çift tırnak içine alır ve içindeki çift tırnak işaretinden kaçar.
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
Bu soruya doğrudan bir cevap değil, ama kendi cevaplarımı ararken buraya geldiğim için, bunu burada paylaşacağım.
Eşleşmeniz gereken on veya yüz milyonlarca anahtarınız varsa, burada verilen yanıtlar Redis'in önemli miktarda (dakika?) Yanıt vermemesine ve bellek tüketimi nedeniyle potansiyel olarak çökmesine neden olur (arka planda kaydetme ameliyatın ortasında tekmelemek).
Aşağıdaki yaklaşım yadsınamaz derecede çirkin, ama daha iyi bir yaklaşım bulamadım. Atomiklik burada söz konusu değil, bu durumda ana hedef, Redis'i yukarı ve% 100 oranında duyarlı tutmaktır. Tüm anahtarlarınız bir veritabanında varsa ve herhangi bir desenle eşleşmeniz gerekmiyorsa, mükemmel çalışır, ancak doğayı engellediği için http://redis.io/commands/FLUSHDB'yi kullanamazsınız .
Fikir basit: bir döngüde çalışan ve anahtarları almak için http://redis.io/commands/SCAN veya http://redis.io/commands/RANDOMKEY gibi O (1) işlemini kullanan bir komut dosyası yazın, kalıbı eşleştirin (gerekiyorsa) ve http://redis.io/commands/DEL onları tek tek.
Bunu yapmanın daha iyi bir yolu varsa, lütfen bana bildirin, cevabı güncelleyeceğim.
Bir komisyon görevi olarak, rasgele bir tuşla örnek uygulama, bir engelleme yerine aşağıdaki gibi bir şeyin yerine geçmez 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'te "Şubeyi kaldır" işlevselliği ile basit bir şekilde uygulanır , sadece kaldırmak istediğiniz dalı seçin.
Yukarıda belirtilen yöntemlerin çoğunu denedim ama benim için çalışmadılar, bazı aramalardan sonra bu noktaları buldum:
-n [number]
del
ancak anahtarların binlerce, milyonlarca varsa kullanmak daha iyidir unlink
, çünkü bağlantının kaldırılmasını engellenmeyen olan del fazla bilgi ziyaret için, bu sayfa engelliyor ise del vs unlinkkeys
del gibi ve engelliyorbu yüzden tuşları kalıba göre silmek için bu kodu kullandım:
redis-cli -n 2 --scan --pattern '[your pattern]' | xargs redis-cli -n 2 unlink
Şimdi reklam, bir redis istemcisi kullanabilir ve önce ilk SCAN (desen eşleşmeyi destekler) ve ardından her anahtarı ayrı ayrı DEL yapabilirsiniz.
Ancak, burada bir pıtırtı eşleştirme-del oluşturmak için resmi redis github üzerinde bir sorun var , gidin yararlı bulursanız biraz sevgi göster!
Bazı araçlara sahip olmak veya Lua ifadesini yürütmekle ilgili tüm cevapları destekliyorum.
Benim tarafımdan bir seçenek daha:
Üretim ve üretim öncesi veritabanlarımızda binlerce anahtar vardır. Zaman zaman bazı anahtarları silmemiz (bazı maskeler ile), bazı kriterler vb. İle değiştirmemiz gerekir. Elbette, CLI'den manuel olarak yapmanın hiçbir yolu yoktur, özellikle de parçalama (her fizikselde 512 mantıksal dbs).
Bu amaçla tüm bu işleri yapan java istemci aracı yazıyorum. Anahtarların silinmesi durumunda yardımcı program çok basit olabilir, sadece bir sınıf var:
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();
}
}
Aşağıdaki komut benim için çalıştı.
redis-cli -h redis_host_url KEYS "*abcd*" | xargs redis-cli -h redis_host_url DEL
Bahar RedisTemplate kendisi işlevselliği sağlar. En son sürümdeki RedissonClient "deleteByPattern" işlevini kullanımdan kaldırmıştır.
Set<String> keys = redisTemplate.keys("geotag|*");
redisTemplate.delete(keys);
keys
ve delete
yöntemler çağırma arasında görünebilir .