วิธีการลบคีย์ที่ตรงกับรูปแบบโดยใช้ Redis แบบอะตอม


576

ใน Redis DB ของฉันฉันมีprefix:<numeric_id>แฮชจำนวนหนึ่ง

บางครั้งฉันต้องการล้างพวกเขาทั้งหมดด้วยวิธีอะตอม ฉันจะทำสิ่งนี้โดยไม่ใช้กลไกการล็อคแบบกระจายได้อย่างไร


สวัสดี Steve มีปัญหาบางอย่างกับเว็บไซต์ของฉันฉันได้เพิ่มไว้ในบล็อกอื่น ๆ ของฉันmind-geek.net/nosql/redis/delete-keys-specific-expiry-timeหวังว่านี่จะช่วยได้
Gaurav Tewari

43
นี่เป็นสถานการณ์ทั่วไปที่ฉันต้องการให้ทีม Redis พิจารณาเพิ่มคำสั่งพื้นฐาน
ทอดด์ Menier

ทุกวันนี้คุณสามารถทำสิ่งนี้กับ Lua ดูด้านล่าง
Alexander Gladysh

3
@ToddMenier เพิ่งแนะนำได้รับเหตุผลกลับมาว่าทำไมมันจะไม่เกิดขึ้น: github.com/antirez/redis/issues/2042
Ray

1
ผู้คนจำนวนมากถามคำถามที่เกี่ยวข้องเกี่ยวกับวิธีจัดการกับคีย์จำนวนมากกุญแจที่มีอักขระพิเศษ ฯลฯ ฉันสร้างคำถามแยกต่างหากเนื่องจากเราประสบปัญหานี้แล้วและฉันไม่คิดว่าคำตอบจะโพสต์ในคำถามนี้ นี่คือคำถามอื่น ๆ : stackoverflow.com/questions/32890648/ …
jakejgordon

คำตอบ:


431

เริ่มต้นด้วย 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


23
หมายเหตุสำคัญ: สิ่งนี้จะล้มเหลวหากคุณมีคีย์มากกว่าสองพันตัวที่ตรงกับคำนำหน้า
นาธานออสมัน

93
อันนี้ใช้ได้กับกุญแจจำนวนมาก: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:*
sheerun

181
โอชา ... Redis ถูกใช้บ่อยๆเหมือนกับแคชคีย์ / ร้านค้า ดูเหมือนว่าdel prefix:* จะเป็นการดำเนินการขั้นพื้นฐาน: /
Ray

5
@ Ray ตรงไปตรงมาถ้าคุณต้องการคุณสมบัติที่คุณควรแบ่งพาร์ติชันข้อมูลโดยฐานข้อมูลหรือเซิร์ฟเวอร์และใช้ flush / flushdb
Marc Gravell

9
ใช่มันล้มเหลวหากไม่มีคีย์ตรงกับรูปแบบ เพื่อแก้ไขว่าฉันเพิ่มคีย์เริ่มต้น:EVAL "return redis.call('del', 'defaultKey', unpack(redis.call('keys', ARGV[1])))" 0 prefix:*
manuelmhtr

706

ดำเนินการใน bash:

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

UPDATE

โอเคฉันเข้าใจแล้ว. เกี่ยวกับวิธีนี้: เก็บคำนำหน้าเพิ่มเติมที่เพิ่มขึ้นในปัจจุบันและเพิ่มไปยังคีย์ทั้งหมดของคุณ ตัวอย่างเช่น:

คุณมีค่าเช่นนี้:

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

เมื่อคุณต้องการกำจัดข้อมูลคุณเปลี่ยน prefix_actuall ก่อน (เช่น set prefix_prefix_actuall = 3) ดังนั้นแอปพลิเคชันของคุณจะเขียนข้อมูลใหม่ไปยังคำนำหน้าคีย์: 3: 1 และคำนำหน้า: 3: 2 จากนั้นคุณสามารถนำค่าเก่าได้อย่างปลอดภัยจากส่วนนำหน้า: 2: 1 และส่วนนำหน้า: 2: 2 และล้างคีย์เก่า


14
ขออภัยนี่ไม่ใช่การลบอะตอม บางคนอาจเพิ่มคีย์ใหม่ระหว่าง KEYS และ DEL ฉันไม่ต้องการลบสิ่งเหล่านั้น
Alexander Gladysh

36
คีย์ที่จะถูกสร้างหลังจากคำสั่งของ KEYS จะไม่ถูกลบ
Casey

6
ฉันแค่ต้องเคลียร์คีย์ที่ไม่ดีออกไปดังนั้นคำตอบแรกของ Casey นั้นก็เกิดขึ้นยกเว้นฉันต้องย้ายคีย์นอกเครื่องหมายคำพูด: คำนำหน้า Redis-cli "คำนำหน้า: *" | xargs redis-cli DEL
jslatts

19
คำตอบแรกยังช่วยฉันออก อีกตัวแปรหนึ่งหากคีย์ redis ของคุณมีเครื่องหมายคำพูดหรือตัวละครอื่น ๆ ที่ทำให้ xargs เลอะ:redis-cli KEYS "prefix:*" | xargs --delim='\n' redis-cli DEL
คิดใหม่

18
หากคุณมีฐานข้อมูลที่หลากหลาย (พื้นที่สำคัญ) นี่คือเคล็ดลับ: ให้บอกว่าคุณต้องลบคีย์ใน db3:redis-cli -n 3 KEYS "prefix:*" | xargs redis-cli -n 3 DEL
Christoffer

73

ต่อไปนี้เป็นรุ่นตัวแทนที่ทำงานได้อย่างสมบูรณ์และมีการลบสัญลักษณ์ตัวแทนที่ใช้ใน 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

อย่างที่คิคิโตะแนะนำ


10
รหัสด้านบนจะเป็นรหัสถังถ้าคุณมีคีย์จำนวนมาก (ข้อผิดพลาดคือ "องค์ประกอบมากเกินกว่าจะแกะออก" ฉันแนะนำให้ใช้ลูปในส่วน Lua:for _,k in ipairs(redis.call('keys', KEYS[1])) do redis.call('del', k) end
kikito

@ kikito ใช่ถ้า lua ไม่สามารถขยายสแต็กเป็นจำนวนของคีย์ที่คุณต้องการลบ (ส่วนใหญ่เนื่องจากหน่วยความจำไม่เพียงพอ) คุณจะต้องทำด้วยลูป for ฉันจะไม่แนะนำให้ทำเช่นนี้จนกว่าคุณจะต้อง
Eli

1
Lua unpackแปลงตารางใน "รายการตัวแปรอิสระ" (ภาษาอื่นเรียกว่าexplode) แต่จำนวนสูงสุดไม่ได้ขึ้นอยู่กับหน่วยความจำ syste; มันถูกแก้ไขใน lua ผ่านLUAI_MAXSTACKค่าคงที่ ใน Lua 5.1 และ LuaJIT คือ 8000 และใน Lua 5.2 คือ 100000 แนะนำให้ใช้ตัวเลือกสำหรับการวนซ้ำ IMO
kikito

1
เป็นที่น่าสังเกตว่าการเขียนสคริปต์ lua นั้นมีให้ตั้งแต่ Redis 2.6 ขึ้นไป
wallacer

1
โซลูชันที่ใช้ Lua ใด ๆ จะละเมิดความหมายของEVALเนื่องจากไม่ได้ระบุคีย์ที่จะใช้งานล่วงหน้า ควรทำงานกับอินสแตนซ์เดียว แต่อย่าคาดหวังให้ทำงานกับ Redis Cluster
Kevin Christopher Henry

66

ข้อจำกัดความรับผิดชอบ: โซลูชันต่อไปนี้ไม่มีอะตอมมิก

เริ่มต้นด้วย v2.8 คุณจริงๆต้องการใช้SCANคำสั่งแทนแป้น [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] KEYSเป็นคำสั่งอันตรายที่อาจส่งผลให้เกิด DoS ต่อไปนี้เป็นคำพูดจากหน้าเอกสารประกอบ:

คำเตือน:พิจารณา KEYS เป็นคำสั่งที่ควรใช้ในสภาพแวดล้อมการผลิตด้วยความระมัดระวังอย่างยิ่งเท่านั้น มันอาจทำลายประสิทธิภาพเมื่อมีการดำเนินการกับฐานข้อมูลขนาดใหญ่ คำสั่งนี้มีไว้สำหรับการดีบักและการดำเนินการพิเศษเช่นการเปลี่ยนเค้าโครงพื้นที่คีย์ของคุณ อย่าใช้ KEYS ในรหัสแอปพลิเคชันปกติของคุณ หากคุณกำลังมองหาวิธีหากุญแจในชุดย่อยของ keyspace ของคุณให้พิจารณาใช้ชุด

UPDATE:หนึ่งซับสำหรับเอฟเฟกต์พื้นฐานเดียวกัน -

$ redis-cli --scan --pattern "*:foo:bar:*" | xargs -L 100 redis-cli DEL

9
อย่างไรก็ตามการหลีกเลี่ยง KEYS ถือเป็นแนวปฏิบัติที่ดีที่สุดดังนั้นนี่จึงเป็นทางออกที่ยอดเยี่ยมในทุกที่ที่ไม่มีการลบอะตอมมิก
fatal_error

สิ่งนี้ได้ผลสำหรับฉัน แต่คีย์ของฉันที่จะเกิดขึ้นในฐานข้อมูล 1. ดังนั้นผมจึงต้องเพิ่ม-n 1ให้กับแต่ละredis-cliภาวนา:redis-cli -n 1 --scan --pattern "*:foo:bar:*" | xargs -L 100 redis-cli -n 1 DEL
ร็อบฮันเซน

โปรดทราบว่าวิธีนี้ใช้ไม่ได้หากกุญแจของคุณมีตัวอักษรพิเศษ
mr1031011

ค้นหาที่น่าสนใจและมีคุณค่า ... ฉันสงสัยว่าจะมีวิธีอ้างสิ่งต่าง ๆ สำหรับ xargs ...
Itamar Haber

-L 100 ทำอะไร
Aparna

41

สำหรับผู้ที่มีปัญหาในการแยกวิเคราะห์คำตอบอื่น ๆ :

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


37

ฉันใช้คำสั่งด้านล่างใน redis 3.2.8

redis-cli KEYS *YOUR_KEY_PREFIX* | xargs redis-cli DEL

คุณสามารถขอความช่วยเหลือเพิ่มเติมเกี่ยวกับการค้นหารูปแบบแป้นได้จากที่นี่: - https://redis.io/commands/keys ใช้รูปแบบ 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);
            }
        }

ขอบคุณ :)


23

วิธีการแก้ปัญหาของ @ mcdizle ไม่ทำงานใช้งานได้กับหนึ่งรายการเท่านั้น

อันนี้ใช้ได้กับทุกปุ่มที่มีคำนำหน้าเหมือนกัน

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

หมายเหตุ:คุณควรแทนที่ 'คำนำหน้า' ด้วยคำนำหน้าคีย์ของคุณ ...


2
ใช้ lua เป็น loooooot เร็วกว่าการใช้ xargs เพื่อ 10 ^ 4
deepak

22

คุณยังสามารถใช้คำสั่งนี้เพื่อลบคีย์: -

สมมติว่ามีคีย์หลายประเภทใน Redis like- ของคุณ

  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คือ a SITENAMEและกุญแจเหล่านี้จะเกี่ยวข้องกับผลิตภัณฑ์และประเภทของเว็บไซต์ E-Commerce และสร้างขึ้นโดย 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

3
ขอบคุณ แต่การส่งออกไปยังท่อredis-cli delไม่ใช่อะตอม
Alexander Gladysh

13

หากคุณมีที่ว่างในชื่อของคีย์คุณสามารถใช้สิ่งนี้ในทุบตี:

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

10

@ คำตอบของ itamar นั้นยอดเยี่ยม แต่การแยกคำตอบไม่ได้ผลสำหรับฉันโดยเฉพาะ ในกรณีที่ไม่มีกุญแจในการสแกนที่ระบุ ทางออกที่ง่ายกว่าอาจมาจากคอนโซลโดยตรง:

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

สิ่งนี้ยังใช้ SCAN ซึ่งเป็นที่นิยมของ KEYS ในการผลิต แต่ไม่ใช่แบบอะตอมมิก


8

ฉันมีปัญหาเดียวกัน ฉันเก็บข้อมูลเซสชันสำหรับผู้ใช้ในรูปแบบ:

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และจากนั้นผมผลักดันkey-x, key-y, key-zในกัญชาที่ (สั่งไม่ได้เรื่องให้ฉัน) และถ้าฉันไม่จำเป็นว่ากัญชาอีกต่อไปผมแค่ทำDEL session:sessionidและข้อมูลทั้งหมดที่เกี่ยวข้องกับ ID แฮชที่หายไป DELคืออะตอมมิกและการเข้าถึงข้อมูล / การเขียนข้อมูลไปยังแฮชคือ O (1)


ทางออกที่ดี แต่ค่าของฉันแฮชตัวเอง และ Redis เก็บแฮชไว้ในแฮชอีกอัน
Alexander Gladysh

3
อย่างไรก็ตามเขตข้อมูลภายในแฮชไม่มีฟังก์ชันการทำงานที่หมดอายุซึ่งบางครั้งก็มีประโยชน์จริงๆ
Evi Song

สำหรับฉันนี่คือคำตอบที่สะอาด / ง่ายที่สุดจนถึงตอนนี้
Sebastien H.

ชุดไม่สมเหตุสมผลหรือไม่
Jack Tuck

5

ผมคิดว่าสิ่งที่อาจช่วยให้คุณเป็นMULTI / EXEC / ทิ้ง แม้ว่าจะไม่เทียบเท่ากับการทำธุรกรรม 100%คุณควรจะสามารถแยกการลบออกจากการอัพเดทอื่น ๆ ได้


4
แต่ฉันไม่สามารถหาวิธีใช้ที่นี่ได้ DEL เป็นอะตอมด้วยตัวเอง (หรือฉันคิดว่า) และฉันไม่สามารถรับค่าจาก KEYS จนกว่าฉันจะทำ EXEC ดังนั้นฉันจึงไม่สามารถใช้ KEYS และ DEL ใน MULTI เดียวกันได้
Alexander Gladysh

5

FYI

  • ใช้ 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 prompt

$ ./clear-redis-key.sh key_head_pattern

5

คำตอบอื่น ๆ อาจไม่ทำงานหากคีย์ของคุณมีตัวอักษรพิเศษ - Guide$CLASSMETADATA][1]ตัวอย่างเช่น การห่อแต่ละคีย์ในเครื่องหมายคำพูดจะทำให้แน่ใจว่าพวกเขาถูกลบอย่างถูกต้อง:

redis-cli --scan --pattern sf_* | awk '{print $1}' | sed "s/^/'/;s/$/'/" | xargs redis-cli del

2
สคริปต์นี้ทำงานได้อย่างสมบูรณ์แบบทดสอบด้วยคีย์มากกว่า 25,000 ปุ่ม
Jordi

1
คุณสามารถเพิ่มเครื่องหมายคำพูดเดี่ยวใน awk โดยใช้นิพจน์ตลกนี้ `awk '{พิมพ์"' "'' '' '$ 1' '' '' '' ''} ''
Roberto Congiu

3

เวอร์ชันที่ใช้ SCAN แทน KEYS (แนะนำสำหรับเซิร์ฟเวอร์ที่ใช้งานจริง) และ--pipeมากกว่า xargs

ฉันชอบไปป์ไลน์มากกว่า xargs เพราะมันมีประสิทธิภาพมากกว่าและทำงานเมื่อคีย์ของคุณมีเครื่องหมายคำพูดหรืออักขระพิเศษอื่น ๆ ที่เชลล์ของคุณลองและตีความ การทดแทน regex ในตัวอย่างนี้ล้อมรอบคีย์ในเครื่องหมายคำพูดคู่และหนีเครื่องหมายคำพูดคู่ใด ๆ ที่อยู่ภายใน

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

วิธีนี้ใช้ได้ผลดีสำหรับฉันแม้จะใช้งานได้ประมาณ 7 ม.!
Danny

2

นี่ไม่ใช่คำตอบที่ตรงกับคำถาม แต่เมื่อฉันมาถึงที่นี่เมื่อค้นหาคำตอบของฉันเองฉันจะแบ่งปันที่นี่

หากคุณมีคีย์นับสิบหรือหลายร้อยล้านที่คุณต้องจับคู่คำตอบที่ให้ไว้ที่นี่จะทำให้ Redis ไม่ตอบสนองต่อจำนวนเวลา (นาที?) ที่สำคัญและอาจเกิดปัญหาเนื่องจากการใช้หน่วยความจำ เตะเข้ากลางการปฏิบัติการของคุณ)

วิธีการต่อไปนี้น่าเกลียดอย่างปฏิเสธไม่ได้ แต่ฉันไม่พบวิธีที่ดีกว่า ปรมาณูเป็นคำถามที่นี่ในกรณีนี้เป้าหมายหลักคือการรักษา Redis และตอบสนอง 100% ของเวลา มันจะทำงานได้อย่างสมบูรณ์ถ้าคุณมีคีย์ทั้งหมดของคุณในฐานข้อมูลหนึ่งและคุณไม่จำเป็นต้องตรงกับรูปแบบใด ๆ แต่ไม่สามารถใช้http://redis.io/commands/FLUSHDBเพราะมันเป็นธรรมชาติที่ปิดกั้น

แนวคิดง่าย: เขียนสคริปต์ที่ทำงานเป็นวนรอบและใช้การดำเนินการ O (1) เช่นhttp://redis.io/commands/SCANหรือhttp://redis.io/commands/RANDOMKEYเพื่อรับคีย์ตรวจสอบว่าพวกเขา จับคู่รูปแบบ (ถ้าคุณต้องการ) และhttp://redis.io/commands/DELพวกเขาทีละคน

หากมีวิธีที่ดีกว่าในการทำโปรดแจ้งให้เราทราบฉันจะอัปเดตคำตอบ

ตัวอย่างการนำไปใช้กับ 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

2

มันใช้งานง่ายผ่านฟังก์ชั่น "ลบสาขา" ในFastoRedisเพียงเลือกสาขาที่คุณต้องการลบ

ป้อนคำอธิบายรูปภาพที่นี่


มันทำแบบอะตอมหรือไม่? และสิ่งนี้จะช่วยทำในรหัสได้อย่างไร
Matthew อ่าน


1

ฉันลองวิธีส่วนใหญ่ที่กล่าวถึงข้างต้น แต่พวกเขาไม่ได้ผลสำหรับฉันหลังจากการค้นหาบางครั้งฉันพบประเด็นเหล่านี้:

  • หากคุณมีมากกว่าหนึ่ง db บน redis คุณควรตรวจสอบฐานข้อมูลโดยใช้ -n [number]
  • ถ้าคุณใช้ปุ่มไม่กี่ปุ่มdelแต่ถ้ามีหลายพันหรือหลายล้านปุ่มมันจะดีกว่าที่จะใช้unlinkเพราะการยกเลิกการเชื่อมโยงนั้นไม่ใช่การปิดกั้นในขณะที่เดลกำลังปิดกั้นสำหรับข้อมูลเพิ่มเติมโปรดเยี่ยมชมหน้านี้unlink vs del
  • ยังkeysเป็นเหมือนเดลและกำลังบล็อกอยู่

ดังนั้นฉันใช้รหัสนี้เพื่อลบคีย์ตามรูปแบบ:

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

0

มวลปรมาณูของคนจนลบ?

บางทีคุณอาจกำหนดให้พวกเขาทั้งหมดไปที่ EXPIREAT ในวินาทีเดียวกัน - เหมือนไม่กี่นาทีในอนาคต - จากนั้นรอจนกว่าจะถึงเวลานั้นและเห็นพวกเขาทั้งหมด "ทำลายตัวเอง" ในเวลาเดียวกัน

แต่ฉันไม่แน่ใจจริงๆว่าอะตอมจะเป็นอย่างไร


0

โฆษณาของตอนนี้คุณสามารถใช้ไคลเอนต์ redis และดำเนินการ SCAN แรก (รองรับการจับคู่รูปแบบ) จากนั้นลบแต่ละคีย์แต่ละรายการ

อย่างไรก็ตามมีปัญหาเกี่ยวกับ github redis เป็นทางการในการสร้าง patter-matching-del ที่นี่ไปแสดงความรักถ้าคุณพบว่ามีประโยชน์!


-1

ฉันสนับสนุนคำตอบทั้งหมดที่เกี่ยวข้องกับการมีเครื่องมือหรือรันนิพจน์ Lua

อีกหนึ่งตัวเลือกจากด้านข้างของฉัน:

ในฐานข้อมูลการผลิตและการผลิตล่วงหน้าของเรามีกุญแจนับพัน บางครั้งเราจำเป็นต้องลบคีย์บางตัว (โดยมาสก์บางตัว) ปรับเปลี่ยนตามเกณฑ์บางอย่าง ฯลฯ แน่นอนว่าไม่มีวิธีการทำด้วยตนเองจาก CLI โดยเฉพาะอย่างยิ่งการมีเศษ (512 dbs เชิงตรรกะในแต่ละกายภาพ)

เพื่อจุดประสงค์นี้ฉันเขียนเครื่องมือไคลเอนต์ java ที่ทำงานทั้งหมดนี้ ในกรณีที่มีการลบกุญแจยูทิลิตี้สามารถง่ายมากเพียงหนึ่งชั้นมี:

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

}


-3

สปริง RedisTemplate ตัวเองให้การทำงาน RedissonClient ในเวอร์ชั่นล่าสุดเลิกใช้งานฟังก์ชั่น "deleteByPattern"

Set<String> keys = redisTemplate.keys("geotag|*");
redisTemplate.delete(keys);

2
ฉันอัปเดตโค้ดตัวอย่าง Redisson รหัสของคุณไม่ได้อยู่ในแนวทางของอะตอมเหมือน Redisson มีปุ่มใหม่ที่อาจปรากฏระหว่างkeysและdeleteวิธีการเรียกใช้
Nikita Koksharov
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.