मेरे रेडिस डीबी में मेरे पास कई prefix:<numeric_id>हैश हैं।
कभी-कभी मैं उन सभी को परमाणु रूप से शुद्ध करना चाहता हूं। कुछ वितरित लॉकिंग तंत्र का उपयोग किए बिना मैं यह कैसे करूं?
मेरे रेडिस डीबी में मेरे पास कई prefix:<numeric_id>हैश हैं।
कभी-कभी मैं उन सभी को परमाणु रूप से शुद्ध करना चाहता हूं। कुछ वितरित लॉकिंग तंत्र का उपयोग किए बिना मैं यह कैसे करूं?
जवाबों:
रेडिस 2.6.0 से शुरू होकर, आप लुआ स्क्रिप्ट चला सकते हैं, जो परमाणु रूप से निष्पादित होती है। मैंने कभी एक नहीं लिखा है, लेकिन मुझे लगता है कि यह कुछ इस तरह दिखाई देगा
EVAL "return redis.call('del', unpack(redis.call('keys', ARGV[1])))" 0 prefix:[YOUR_PREFIX e.g delete_me_*]
चेतावनी : जैसा कि रेडिस दस्तावेज़ कहता है, प्रदर्शन मैटर्स के कारण,
keysकमांड को उत्पादन में नियमित संचालन के लिए उपयोग नहीं करना चाहिए, यह कमांड डीबगिंग और विशेष संचालन के लिए है। अधिक पढ़ें
EVAL दस्तावेज़ देखें ।
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:* कि एक मौलिक ऑपरेशन होना चाहिए: /
EVAL "return redis.call('del', 'defaultKey', unpack(redis.call('keys', ARGV[1])))" 0 prefix:*
बाश में निष्पादित करें:
redis-cli KEYS "prefix:*" | xargs redis-cli DEL
अपडेट करें
ठीक हैं मैं समझ गया। इस तरह के बारे में क्या: वर्तमान अतिरिक्त वृद्धिशील उपसर्ग को संग्रहीत करें और इसे अपनी सभी कुंजियों में जोड़ें। उदाहरण के लिए:
आपके पास इस तरह के मान हैं:
prefix_prefix_actuall = 2
prefix:2:1 = 4
prefix:2:2 = 10
जब आपको डेटा शुद्ध करने की आवश्यकता होती है, तो आप पहले प्रीफ़िक्स_एक्ट्यूएल बदलते हैं (उदाहरण के लिए सेट प्रीफ़िक्स_प्रिफ़िक्स_एक्टुआल = 3), इसलिए आपका एप्लिकेशन कुंजी उपसर्ग: 3: 1 और उपसर्ग: 3: 2 में नया डेटा लिखेगा। फिर आप उपसर्ग: 2: 1 और उपसर्ग: 2: 2 से पुराने मान सुरक्षित रूप से ले सकते हैं और पुरानी कुंजियों को शुद्ध कर सकते हैं।
redis-cli KEYS "prefix:*" | xargs --delim='\n' redis-cli DEL
redis-cli -n 3 KEYS "prefix:*" | xargs redis-cli -n 3 DEL
यहां लुआ में लागू वाइल्डकार्ड डिलीट का पूरी तरह से काम और परमाणु संस्करण है। यह बहुत ही कम नेटवर्क के पीछे और आगे xargs संस्करण की तुलना में बहुत तेज़ी से चलेगा, और यह पूरी तरह से परमाणु है, जब तक यह खत्म नहीं होता तब तक रेडिस के खिलाफ किसी भी अन्य अनुरोध को अवरुद्ध करता है। यदि आप 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% उसे जाता है।
संपादित करें: प्रति किकोइटो की टिप्पणी के अनुसार, यदि आपके पास अपने रेडिस सर्वर में मुफ्त मेमोरी से हटाने के लिए अधिक कुंजी है, तो आप "बहुत सारे तत्वों को अनपैक करने के लिए" त्रुटि में चलेंगे । उस मामले में, करें:
for _,k in ipairs(redis.call('keys', ARGV[1])) do
redis.call('del', k)
end
जैसा कि किकिटो ने सुझाव दिया था।
for _,k in ipairs(redis.call('keys', KEYS[1])) do redis.call('del', k) end
unpackएक तालिका को "स्वतंत्र चर की सूची" में बदल देता है (अन्य भाषाएं कहती हैं कि explode) लेकिन अधिकतम संख्या सिस्ट मेमोरी पर निर्भर नहीं है; यह स्थिर के माध्यम से लुआ में तय हो गया LUAI_MAXSTACKहै। Lua 5.1 और LuaJIT में यह 8000 है और Lua 5.2 में 100000 है। लूप विकल्प के लिए IMO की सिफारिश की गई है।
EVALक्योंकि यह उन कुंजियों को पहले से निर्दिष्ट नहीं करता है जिन पर यह काम करेगा। इसे एक ही उदाहरण पर काम करना चाहिए, लेकिन यह उम्मीद न करें कि यह रेडिस क्लस्टर के साथ काम करेगा।
अस्वीकरण: निम्नलिखित समाधान परमाणुता प्रदान नहीं करता है ।
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
[१] KEYS एक खतरनाक कमांड है जो संभावित रूप से DoS में परिणाम कर सकता है। निम्नलिखित इसके प्रलेखन पृष्ठ से एक उद्धरण है:
चेतावनी: कुंजी को एक कमांड के रूप में माना जाता है जिसे केवल अत्यधिक सावधानी के साथ उत्पादन वातावरण में उपयोग किया जाना चाहिए। बड़े डेटाबेस के खिलाफ निष्पादित होने पर यह प्रदर्शन को बर्बाद कर सकता है। यह कमांड डीबगिंग और विशेष परिचालनों के लिए है, जैसे कि आपका कीस्पेस लेआउट बदलना। अपने नियमित एप्लिकेशन कोड में कुंजियों का उपयोग न करें। यदि आप अपने कुंजी क्षेत्र के सबसेट में कुंजियाँ खोजने का तरीका खोज रहे हैं, तो सेट का उपयोग करने पर विचार करें।
अद्यतन: एक ही मूल प्रभाव के लिए एक लाइनर -
$ redis-cli --scan --pattern "*:foo:bar:*" | xargs -L 100 redis-cli DEL
-n 1प्रत्येक redis-cliआह्वान में शामिल होना था:redis-cli -n 1 --scan --pattern "*:foo:bar:*" | xargs -L 100 redis-cli -n 1 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
मैं रेडिस 3.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);
}
}
धन्यवाद :)
@ mcdizle का समाधान काम नहीं कर रहा है यह केवल एक प्रविष्टि के लिए काम करता है।
यह एक ही उपसर्ग के साथ सभी कुंजी के लिए काम करता है
EVAL "for i, name in ipairs(redis.call('KEYS', ARGV[1])) do redis.call('DEL', name); end" 0 prefix*
नोट: आपको अपने प्रमुख उपसर्ग के साथ 'उपसर्ग' को बदलना चाहिए ...
कुंजी को हटाने के लिए आप इस कमांड का उपयोग कर सकते हैं: -
मान लीजिए कि आपकी लालियों में कई तरह की चाबियां हैं-
पूर्व- ' xyz_category_fpc ' यहाँ xyz एक है sitename , और इन कुंजियों उत्पादों और एक ई-कॉमर्स साइट के श्रेणियों से संबंधित और पांचवें वेतन आयोग द्वारा उत्पन्न कर रहे हैं।
यदि आप इस आदेश का उपयोग नीचे के रूप में करते हैं-
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 flushall
redis-cli flushdb
redis-cli delपरमाणु नहीं है।
@ इटमार का उत्तर बहुत अच्छा है, लेकिन उत्तर की पार्सिंग मेरे लिए नहीं जासूसी का काम कर रही थी। उस स्थिति में जहां दिए गए स्कैन में कोई कुंजी नहीं मिली है। संभवतः कंसोल से सीधे एक सरल समाधान,
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:*- लेकिन रेडिस में ऐसा कोई फ़ंक्शन नहीं है।
मैंने क्या किया: एक हैश के भीतर सत्र डेटा संग्रहीत करें । मैं बस के हैश आईडी के साथ एक हैश बनाने session:sessionidऔर उसके बाद मैं धक्का key-x, key-y, key-zकि हैश में (आदेश नहीं बात मेरे लिए किया था) और अगर मैं जरूरत है कि हैश अब मैं सिर्फ एक ऐसा न DEL session:sessionidऔर उस हैश आईडी से संबद्ध सभी डेटा चला गया है। DELपरमाणु और अभिगम डेटा / हैश को डेटा लिखना हे (1) है।
मुझे लगता है कि MULTI / EXEC / DISCARD क्या आपकी मदद कर सकता है । लेन-देन के 100% समतुल्य नहीं होने पर, आपको डिलीट को अन्य अपडेट से अलग करने में सक्षम होना चाहिए।
FYI करें।
redis-clikeys(यह उपयोग करता है 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
बैश प्रॉम्प्ट पर चलाएं
$ ./clear-redis-key.sh key_head_pattern
Guide$CLASSMETADATA][1]उदाहरण के लिए, यदि आपकी कुंजी में विशेष वर्ण हैं, तो अन्य उत्तर काम नहीं कर सकते हैं । प्रत्येक कुंजी को उद्धरणों में लपेटने से यह सुनिश्चित होगा कि वे ठीक से नष्ट हो जाएंगे:
redis-cli --scan --pattern sf_* | awk '{print $1}' | sed "s/^/'/;s/$/'/" | xargs redis-cli del
कुंजी के बजाय SCAN का उपयोग कर एक संस्करण (उत्पादन सर्वर के लिए अनुशंसित) और --pipexargs के बजाय।
मैं 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
यह प्रश्न का सीधा उत्तर नहीं है, लेकिन जब से मैं अपने स्वयं के उत्तरों की खोज कर रहा हूं, मैं इसे यहां साझा करूंगा।
यदि आपके पास दसियों या सैकड़ों लाखों कीज़ हैं जिन्हें आपको मिलान करना है, तो यहां दिए गए उत्तर महत्वपूर्ण समय (मिनटों?) के लिए रिडिस गैर-उत्तरदायी होंगे और मेमोरी खपत के कारण संभावित रूप से क्रैश हो सकते हैं (सुनिश्चित करें, बैकग्राउंड सेव करें आपके ऑपरेशन के बीच में किक)।
निम्नलिखित दृष्टिकोण निर्विवाद रूप से बदसूरत है, लेकिन मुझे एक बेहतर नहीं मिला। एटमॉसिटी यहां सवालों से बाहर है, इस मामले में मुख्य लक्ष्य रेडिस को बनाए रखना है और समय का 100% उत्तरदायी है। यह पूरी तरह से काम करेगा यदि आपके पास डेटाबेस में आपकी सभी चाबियाँ हैं और आपको किसी भी पैटर्न से मेल खाने की आवश्यकता नहीं है, लेकिन प्रकृति को अवरुद्ध करने के कारण http://redis.io/commands/FLUSHDB का उपयोग नहीं कर सकते ।
आइडिया सरल है: एक स्क्रिप्ट लिखें जो एक लूप में चलती है और http://redis.io/commands/SCAN या http://redis.io/commands/RANDOMKEY जैसे O (1) ऑपरेशन का उपयोग कर कुंजी, चेक प्राप्त करता है यदि वे पैटर्न से मिलान करें (यदि आपको इसकी आवश्यकता है) और http://redis.io/commands/DEL उन्हें एक-एक करके।
यदि ऐसा करने का कोई बेहतर तरीका है, तो कृपया मुझे बताएं, मैं उत्तर को अपडेट करूंगा।
उदाहरण के लिए रूबी में रैंडम के साथ कार्यान्वयन, एक रेक कार्य के रूप में, कुछ का एक गैर अवरुद्ध विकल्प 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 में "निकालें शाखा" कार्यक्षमता के माध्यम से सरल है , बस उस शाखा का चयन करें जिसे आप निकालना चाहते हैं।
कृपया इस आदेश का उपयोग करें और प्रयास करें:
redis-cli --raw keys "$PATTERN" | xargs redis-cli del
मैंने ऊपर बताए गए अधिकांश तरीकों की कोशिश की, लेकिन उन्होंने मेरे लिए काम नहीं किया, कुछ खोजों के बाद मुझे ये अंक मिले:
-n [number]del, लेकिन अगर वहाँ हजारों या कुंजी के लाखों रहे हैं इसका इस्तेमाल बेहतर है unlinkक्योंकि अनलिंक गैर अवरुद्ध है , जबकि डेल अधिक जानकारी के लिए, ब्लॉक कर रहा है यह पेज अनलिंक बनाम डेलkeysडेल की तरह हैं और अवरुद्ध हैइसलिए मैंने पैटर्न द्वारा कुंजियों को हटाने के लिए इस कोड का उपयोग किया:
redis-cli -n 2 --scan --pattern '[your pattern]' | xargs redis-cli -n 2 unlink
मैं कुछ उपकरण होने या लूआ अभिव्यक्ति को निष्पादित करने से संबंधित सभी उत्तरों का समर्थन करता हूं।
मेरी तरफ से एक और विकल्प:
हमारे उत्पादन और पूर्व-उत्पादन डेटाबेस में हजारों कीज़ हैं। समय-समय पर हमें कुछ चाबियों (कुछ मुखौटा द्वारा) को हटाने की जरूरत है, कुछ मानदंडों आदि द्वारा संशोधित किया जाता है, ज़ाहिर है, सीएलआई से इसे मैन्युअल रूप से करने का कोई तरीका नहीं है, विशेष रूप से शार्डिंग (प्रत्येक भौतिक में 512 तार्किक डीएस)।
इस काम के लिए मैं जावा क्लाइंट टूल लिखता हूं जो यह सब काम करता है। चाबियाँ हटाने के मामले में उपयोगिता बहुत सरल हो सकती है, केवल एक ही वर्ग वहां:
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
स्प्रिंग RedisTemplate ही कार्यक्षमता प्रदान करता है। नवीनतम संस्करण में RedissonClient ने "deleteByPattern" कार्यक्षमता को हटा दिया है।
Set<String> keys = redisTemplate.keys("geotag|*");
redisTemplate.delete(keys);
keysऔर deleteविधियों के इनवॉइस के बीच प्रकट हो सकती हैं ।