ฉันต้องการให้คีย์ทั้งหมดในแฮช redis หมดอายุซึ่งเก่ากว่า 1 เดือน
ฉันต้องการให้คีย์ทั้งหมดในแฮช redis หมดอายุซึ่งเก่ากว่า 1 เดือน
คำตอบ:
นี้เป็นไปไม่ได้เพื่อประโยชน์ของการรักษา Redis ง่าย
Quoth Antirez ผู้สร้าง Redis:
สวัสดีเป็นไปไม่ได้ให้ใช้คีย์ระดับบนสุดที่แตกต่างกันสำหรับฟิลด์นั้น ๆ หรือจัดเก็บพร้อมกับฟิลด์อื่นที่ยื่นพร้อมเวลาหมดอายุดึงข้อมูลทั้งสองและแจ้งให้แอปพลิเคชันเข้าใจว่ายังคงถูกต้องหรือไม่ขึ้นอยู่กับ เวลาปัจจุบัน
Redis ไม่สนับสนุนการมีTTL
แฮชอื่นนอกเหนือจากคีย์บนสุดซึ่งจะทำให้แฮชทั้งหมดหมดอายุ หากคุณกำลังใช้คลัสเตอร์แบบชาร์ดมีวิธีอื่นที่คุณสามารถใช้ได้ แนวทางนี้อาจไม่มีประโยชน์ในทุกสถานการณ์และลักษณะการทำงานอาจแตกต่างจากที่คาดไว้ ยังคงกล่าวถึง:
เมื่อมีแฮชโครงสร้างโดยทั่วไปจะมีลักษณะดังนี้:
hash_top_key
- child_key_1 -> some_value
- child_key_2 -> some_value
...
- child_key_n -> some_value
เนื่องจากเราต้องการเพิ่มTTL
คีย์ลูกเราจึงย้ายไปที่คีย์บนสุดได้ ประเด็นหลักคือตอนนี้คีย์ควรเป็นชุดค่าผสมhash_top_key
และคีย์ลูก:
{hash_top_key}child_key_1 -> some_value
{hash_top_key}child_key_2 -> some_value
...
{hash_top_key}child_key_n -> some_value
เรากำลังใช้{}
สัญกรณ์ตามวัตถุประสงค์ hash slot
นี้จะช่วยให้ทุกปุ่มเหล่านั้นจะตกอยู่ในที่เดียวกัน คุณสามารถอ่านเพิ่มเติมได้ที่นี่: https://redis.io/topics/cluster-tutorial
ตอนนี้ถ้าเราต้องการดำเนินการแฮชแบบเดียวกันเราสามารถทำได้:
HDEL hash_top_key child_key_1 => DEL {hash_top_key}child_key_1
HGET hash_top_key child_key_1 => GET {hash_top_key}child_key_1
HSET hash_top_key child_key_1 some_value => SET {hash_top_key}child_key_1 some_value [some_TTL]
HGETALL hash_top_key =>
keyslot = CLUSTER KEYSLOT {hash_top_key}
keys = CLUSTER GETKEYSINSLOT keyslot n
MGET keys
HGETALL
น่าสนใจที่นี่คือ อันดับแรกเราจะได้รับhash slot
กุญแจสำหรับลูก ๆ ของเราทั้งหมด จากนั้นเราจะได้รับคีย์สำหรับสิ่งนั้น ๆhash slot
และในที่สุดเราก็ดึงค่าออกมา เราจะต้องระมัดระวังที่นี่ตั้งแต่อาจจะมีมากกว่าn
คีย์ที่hash slot
และยังอาจจะมีคีย์ที่เราไม่ได้สนใจใน hash slot
แต่พวกเขามีเหมือนกัน เราสามารถเขียนLua
สคริปต์เพื่อทำขั้นตอนเหล่านั้นในเซิร์ฟเวอร์ได้โดยเรียกใช้คำสั่งEVAL
หรือ EVALSHA
อีกครั้งคุณต้องคำนึงถึงประสิทธิภาพของแนวทางนี้สำหรับสถานการณ์เฉพาะของคุณ
ข้อมูลอ้างอิงเพิ่มเติม:
มีเฟรมเวิร์กRedisson java ซึ่งใช้แฮชMap
อ็อบเจ็กต์ด้วยการรองรับ TTL รายการ มันใช้hmap
และzset
Redis วัตถุภายใต้ประทุน ตัวอย่างการใช้งาน:
RMapCache<Integer, String> map = redisson.getMapCache('map');
map.put(1, 30, TimeUnit.DAYS); // this entry expires in 30 days
แนวทางนี้มีประโยชน์มากทีเดียว
สิ่งนี้เป็นไปได้ในKeyDBซึ่งเป็น Fork of Redis เนื่องจากเป็น Fork จึงเข้ากันได้กับ Redis อย่างสมบูรณ์และทำงานแทนกันได้
เพียงใช้คำสั่ง EXPIREMEMBER ใช้งานได้กับชุดแฮชและชุดที่เรียงลำดับ
คีย์ย่อยของชื่อคีย์ EXPIREMEMBER [เวลา]
คุณยังสามารถใช้ TTL และ PTTL เพื่อดูวันหมดอายุ
คีย์ย่อยชื่อคีย์ TTL
ดูเอกสารเพิ่มเติมได้ที่นี่: https://docs.keydb.dev/docs/commands/#expiremember
เกี่ยวกับการใช้งาน NodeJS ฉันได้เพิ่มexpiryTime
ฟิลด์ที่กำหนดเองในวัตถุที่ฉันบันทึกใน HASH หลังจากช่วงเวลาหนึ่งฉันล้างรายการ HASH ที่หมดอายุโดยใช้รหัสต่อไปนี้:
client.hgetall(HASH_NAME, function(err, reply) {
if (reply) {
Object.keys(reply).forEach(key => {
if (reply[key] && JSON.parse(reply[key]).expiryTime < (new Date).getTime()) {
client.hdel(HASH_NAME, key);
}
})
}
});
Array.filter
เพื่อสร้างอาร์เรย์keys
เพื่อลบออกจากแฮชจากนั้นส่งผ่านไปยังclient.hdel(HASH_NAME, ...keys)
ในการโทรครั้งเดียว
const keys = Object.keys(reply).filter(key => reply[key] && JSON.parse(reply[key]).expiryTime < Date.now()); client.hdel(HASH_NAME, ...keys);
คุณสามารถ. นี่คือตัวอย่าง
redis 127.0.0.1:6379> hset key f1 1
(integer) 1
redis 127.0.0.1:6379> hset key f2 2
(integer) 1
redis 127.0.0.1:6379> hvals key
1) "1"
2) "1"
3) "2"
redis 127.0.0.1:6379> expire key 10
(integer) 1
redis 127.0.0.1:6379> hvals key
1) "1"
2) "1"
3) "2"
redis 127.0.0.1:6379> hvals key
1) "1"
2) "1"
3) "2"
redis 127.0.0.1:6379> hvals key
หากคุณต้องการให้คีย์ที่เฉพาะเจาะจงหมดอายุในแฮชที่เก่ากว่า 1 เดือน นี้เป็นไปไม่ได้ คำสั่ง Redis expire ใช้สำหรับคีย์ทั้งหมดในแฮช หากคุณตั้งค่าแฮชคีย์รายวันคุณสามารถกำหนดเวลาที่จะใช้งานคีย์ได้
hset key-20140325 f1 1
expire key-20140325 100
hset key-20140325 f1 2
คุณสามารถจัดเก็บคีย์ / ค่าใน Redis แตกต่างกันเพื่อให้บรรลุเป้าหมายนี้โดยเพียงแค่เพิ่มคำนำหน้าหรือเนมสเปซให้กับคีย์ของคุณเมื่อคุณจัดเก็บคีย์เหล่านั้นเช่น "hset_"
รับคีย์ / ค่าGET hset_key
เท่ากับHGET hset key
เพิ่มคีย์ / ค่าSET hset_key value
เท่ากับHSET hset key
รับคีย์ทั้งหมดKEYS hset_*
เท่ากับHGETALL hset
รับ vals ทั้งหมดควรทำใน 2 ops ก่อนอื่นให้รับคีย์ทั้งหมดKEYS hset_*
จากนั้นรับค่าสำหรับแต่ละคีย์
เพิ่มคีย์ / ค่าด้วยTTL หรือหมดอายุซึ่งเป็นหัวข้อคำถาม:
SET hset_key value
EXPIRE hset_key
หมายเหตุ : KEYS
จะค้นหาคีย์ที่ตรงกันในฐานข้อมูลทั้งหมดซึ่งอาจส่งผลต่อประสิทธิภาพโดยเฉพาะอย่างยิ่งหากคุณมีฐานข้อมูลขนาดใหญ่
บันทึก:
KEYS
จะค้นหาคีย์ในฐานข้อมูลทั้งหมดซึ่งอาจส่งผลต่อประสิทธิภาพโดยเฉพาะอย่างยิ่งหากคุณมีฐานข้อมูลขนาดใหญ่ ในขณะที่SCAN 0 MATCH hset_*
อาจจะดีกว่าตราบเท่าที่ไม่ได้ปิดกั้นเซิร์ฟเวอร์ แต่ประสิทธิภาพยังคงเป็นปัญหาในกรณีของฐานข้อมูลขนาดใหญ่
คุณอาจสร้างฐานข้อมูลใหม่เพื่อจัดเก็บคีย์เหล่านี้แยกกันซึ่งคุณต้องการให้หมดอายุโดยเฉพาะหากเป็นคีย์ชุดเล็ก
ขอบคุณ @DanFarrell ที่ให้ความสำคัญกับปัญหาด้านประสิทธิภาพที่เกี่ยวข้องกับ
KEYS
hashset
.. รับ O (1) ตั้ง O (1) รับ O (n) ทั้งหมด
O(n)
จำนวนของสิ่งต่างๆในชุดKEYS
ไปจนถึงจำนวนสิ่งต่างๆในฐานข้อมูล
scan 0 match namespace:*
อาจจะดีกว่าตราบเท่าที่ไม่ได้ปิดกั้นเซิร์ฟเวอร์
เรามีปัญหาเดียวกันที่พูดคุยกันที่นี่
เรามีแฮช Redis ซึ่งเป็นกุญแจสำคัญในรายการแฮช (คู่ชื่อ / ค่า) และเราจำเป็นต้องมีเวลาหมดอายุของแต่ละรายการในแต่ละรายการแฮช
เราดำเนินการนี้โดยการเพิ่มข้อมูลคำนำหน้าจำนวน n ไบต์ที่มีข้อมูลการหมดอายุที่เข้ารหัสเมื่อเราเขียนค่ารายการแฮเรายังตั้งค่าคีย์ให้หมดอายุในเวลาที่มีอยู่ในค่าที่กำลังเขียน
จากนั้นเมื่ออ่านเราจะถอดรหัสคำนำหน้าและตรวจสอบการหมดอายุ นี่เป็นค่าใช้จ่ายเพิ่มเติมอย่างไรก็ตามการอ่านยังคงเป็น O (n) และคีย์ทั้งหมดจะหมดอายุเมื่อรายการแฮชสุดท้ายหมดอายุ
คุณสามารถใช้ Redis Keyspace การแจ้งเตือนโดยใช้และpsubscribe
"__keyevent@<DB-INDEX>__:expired"
ด้วยเหตุนี้ทุกครั้งที่คีย์จะหมดอายุคุณจะได้รับข้อความที่เผยแพร่บนการเชื่อมต่อ redis ของคุณ
สำหรับคำถามของคุณโดยพื้นฐานแล้วคุณจะสร้างคีย์ "ปกติ" ชั่วคราวโดยใช้set
เวลาหมดอายุเป็นวินาที / วินาที ควรตรงกับชื่อของคีย์ที่คุณต้องการลบในชุดของคุณ
เนื่องจากคีย์ชั่วคราวของคุณจะถูกเผยแพร่ไปยังการเชื่อมต่อ redis ของคุณโดยถือไว้"__keyevent@0__:expired"
เมื่อหมดอายุคุณจึงสามารถลบคีย์ของคุณจากชุดเดิมได้อย่างง่ายดายเนื่องจากข้อความจะมีชื่อของคีย์
ตัวอย่างง่ายๆในทางปฏิบัติในหน้านั้น: https://medium.com/@micah1powell/using-redis-keyspace-notifications-for-a-reminder-service-with-node-c05047befec3
doc: https://redis.io/topics/notifications (มองหาแฟล็ก xE)
คุณสามารถใช้Sorted Setใน redis เพื่อรับคอนเทนเนอร์ TTL พร้อมเวลาประทับเป็นคะแนน ตัวอย่างเช่นเมื่อใดก็ตามที่คุณแทรกสตริงเหตุการณ์ลงในชุดคุณสามารถตั้งคะแนนเป็นเวลาของเหตุการณ์ได้ ดังนั้นคุณสามารถรับข้อมูลของหน้าต่างเวลาใดก็ได้โดยการโทร
zrangebyscore "your set name" min-time max-time
ยิ่งไปกว่านั้นเราสามารถหมดอายุได้โดยใช้zremrangebyscore "your set name" min-time max-time
เพื่อลบเหตุการณ์เก่า ๆ
ข้อเสียเปรียบประการเดียวคือคุณต้องทำความสะอาดจากกระบวนการภายนอกเพื่อรักษาขนาดของชุด
คุณสามารถหมดอายุแฮช Redis ได้อย่างง่ายดายเช่นใช้ python
import redis
conn = redis.Redis('localhost')
conn.hmset("hashed_user", {'name': 'robert', 'age': 32})
conn.expire("hashed_user", 10)
นี่จะทำให้คีย์ลูกทั้งหมดในhash hashed_user หมดอายุหลังจาก 10 วินาที
เหมือนกันจาก redis-cli
127.0.0.1:6379> HMSET testt username wlc password P1pp0 age 34
OK
127.0.0.1:6379> hgetall testt
1) "username"
2) "wlc"
3) "password"
4) "P1pp0"
5) "age"
6) "34"
127.0.0.1:6379> expire testt 10
(integer) 1
127.0.0.1:6379> hgetall testt
1) "username"
2) "wlc"
3) "password"
4) "P1pp0"
5) "age"
6) "34"
หลังจาก 10 วินาที
127.0.0.1:6379> hgetall testt
(empty list or set)
hset
hset