Yanıtlar:
Redis'i basit tutmak adına bu mümkün değil .
Redis'in yaratıcısı Quoth Antirez:
Merhaba, bu mümkün değil, ya o belirli alan için farklı bir üst düzey anahtar kullanın ya da sona erme süresi olan başka bir alanla birlikte depolayın, ikisini de alın ve uygulamanın hala geçerli olup olmadığını anlamasına izin verin. şimdiki zaman.
Redis TTL
, tüm karmanın geçerliliğini yitirecek üst anahtar dışındaki karmalara sahip olmayı desteklemez . Parçalanmış bir küme kullanıyorsanız, kullanabileceğiniz başka bir yaklaşım vardır. Bu yaklaşım tüm senaryolarda yararlı olmayabilir ve performans özellikleri beklenenden farklı olabilir. Yine de bahsetmeye değer:
Bir hash elde ederken, yapı temelde şöyle görünür:
hash_top_key
- child_key_1 -> some_value
- child_key_2 -> some_value
...
- child_key_n -> some_value
TTL
Alt anahtarlara eklemek istediğimizden , bunları üst tuşlara taşıyabiliriz. Asıl nokta, anahtarın artık bir hash_top_key
alt anahtar kombinasyonu olması gerektiğidir :
{hash_top_key}child_key_1 -> some_value
{hash_top_key}child_key_2 -> some_value
...
{hash_top_key}child_key_n -> some_value
Biz kullandığınız {}
bilerek gösterim. Bu, tüm bu anahtarların aynı düşmesine izin verir hash slot
. Bununla ilgili daha fazla bilgiyi buradan okuyabilirsiniz: https://redis.io/topics/cluster-tutorial
Şimdi aynı hash işlemlerini yapmak istiyorsak, şunları yapabiliriz:
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
Buradaki ilginç olanı HGETALL
. Önce hash slot
tüm çocuklarımızın anahtarlarını alıyoruz. Sonra o belirli anahtarın anahtarlarını hash slot
alırız ve sonunda değerleri alırız. Burada n
anahtarlardan daha fazlası olabileceğinden hash slot
ve ilgilenmediğimiz anahtarlar da olabileceği için burada dikkatli olmamız gerekiyor ama aynı anahtarlara sahip hash slot
. Lua
Bir EVAL
veya EVALSHA
komutunu çalıştırarak sunucuda bu adımları gerçekleştirmek için bir betik yazabiliriz . Yine, kendi senaryonuz için bu yaklaşımın performansını dikkate almanız gerekir.
Biraz daha referans:
Giriş TTL desteği ile hash nesnesini uygulayan bir Redisson java çerçevesi vardır Map
. Kaputun altındaki nesneleri kullanır hmap
ve zset
Redis. Kullanım örneği:
RMapCache<Integer, String> map = redisson.getMapCache('map');
map.put(1, 30, TimeUnit.DAYS); // this entry expires in 30 days
Bu yaklaşım oldukça kullanışlıdır.
Bu bir Fork of Redis olan KeyDB'de mümkündür . Çünkü bu bir Çatal, Redis ile tamamen uyumludur ve yedek parça olarak çalışır.
Sadece EXPIREMBER komutunu kullanın. Kümeler, karmalar ve sıralanmış kümelerle çalışır.
EXPIREMBER anahtar adı alt anahtarı [saat]
Son kullanma tarihini görmek için TTL ve PTTL'yi de kullanabilirsiniz.
TTL anahtar adı alt anahtarı
Daha fazla belge burada bulunabilir: https://docs.keydb.dev/docs/commands/#expiremember
Bir NodeJS uygulamasıyla ilgili olarak, HASH'e expiryTime
kaydettiğim nesneye özel bir alan ekledim . Daha sonra belirli bir süre sonra, süresi dolan HASH girişlerini aşağıdaki kodu kullanarak temizliyorum:
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
için bir dizi oluşturmak için kullanarak ve keys
ardından bunu client.hdel(HASH_NAME, ...keys)
tek bir çağrıda ileterek daha verimli hale getirebilirsiniz .
const keys = Object.keys(reply).filter(key => reply[key] && JSON.parse(reply[key]).expiryTime < Date.now()); client.hdel(HASH_NAME, ...keys);
Yapabilirsin. İşte bir örnek.
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
Kullanım EXPIRE veya EXPIREAT komut.
1 aydan daha eski olan hash içindeki belirli anahtarların süresinin dolmasını istiyorsanız. Bu mümkün değil. Redis sona erme komutu, karmadaki tüm anahtarlar içindir. Günlük hash anahtarını ayarlarsanız, yaşamak için bir anahtar zamanı ayarlayabilirsiniz.
hset key-20140325 f1 1
expire key-20140325 100
hset key-20140325 f1 2
Bunu başarmak için anahtarları / değerleri Redis'te farklı şekilde depolayabilirsiniz, bunları saklarken anahtarlarınıza bir önek veya ad alanı ekleyerek, örneğin "hset_"
GET hset_key
Şuna eşit bir anahtar / değer alın:HGET hset key
SET hset_key value
Şuna eşit bir anahtar / değer ekleyin:HSET hset key
Tüm anahtarları al KEYS hset_*
eşittirHGETALL hset
Tüm vals 2 işlemde yapılmalıdır, önce tüm anahtarları KEYS hset_*
alın, sonra her anahtarın değerini alın
TTL ile bir anahtar / değer ekleyin veya soru konusu olan son kullanma tarihi:
SET hset_key value
EXPIRE hset_key
Not : KEYS
Anahtarın tüm veritabanında eşleşip eşleşmediğine bakar ve bu, özellikle büyük veritabanınız varsa performansı etkileyebilir.
Not:
KEYS
özellikle büyük bir veritabanınız varsa performansı etkileyebilecek tüm veritabanındaki anahtarı eşleştirmek için arayacaktır. ederken SCAN 0 MATCH hset_*
o sunucuyu engellemez ama yine performans büyük veritabanı durumunda bir sorun olduğu sürece daha iyi olabilir.
Son kullanma tarihini geçmesini istediğiniz bu anahtarları, özellikle küçük anahtarlar ise ayrı ayrı depolamak için yeni bir veritabanı oluşturabilirsiniz.
İle ilgili performans sorununu vurgulayan @DanFarrell'e teşekkürler
KEYS
hashset
.. olsun O (1) ayarlanan O (1) Tüm O (n) olsun
O(n)
şeylerin sayısı, DB'deki şeylerin KEYS
sayısı içindir.
scan 0 match namespace:*
sunucuyu engellemediği sürece daha iyi olabilir
Aynı sorunu burada tartıştık.
Bir Redis hash'imiz var, hash girişleri için bir anahtar (ad / değer çiftleri) ve her bir hash girişinde ayrı son kullanma süreleri tutmamız gerekiyordu.
Bunu, hash giriş değerlerini yazdığımızda kodlanmış sona erme bilgilerini içeren n baytlık önek verisi ekleyerek uyguladık, ayrıca anahtarı, yazılan değerin içerdiği zamanda sona erecek şekilde ayarladık.
Ardından, okurken ön ekin kodunu çözer ve son kullanma tarihini kontrol ederiz. Bu ek bir ek yüktür, ancak okumalar hala O (n) ve son hash girişinin süresi dolduğunda tüm anahtarın süresi dolacaktır.
Redis Keyspace Bildirimlerini psubscribe
ve tuşlarını kullanarak kullanabilirsiniz "__keyevent@<DB-INDEX>__:expired"
.
Bununla birlikte, bir anahtarın süresi dolduğunda, redis bağlantınızda yayınlanan bir mesaj alacaksınız.
Sorunuzla ilgili olarak, temel olarak set
, s / ms cinsinden bir sona erme süresi olan geçici bir "normal" anahtar oluşturursunuz . Setinizde silmek istediğiniz anahtarın adıyla eşleşmelidir.
Geçici anahtarınız, "__keyevent@0__:expired"
süresi dolduğunda redis bağlantınızda yayınlanacağından, mesajda anahtarın adı olacağından anahtarınızı orijinal setinizden kolayca silebilirsiniz.
Bu sayfadaki pratikte basit bir örnek: https://medium.com/@micah1powell/using-redis-keyspace-notifications-for-a-reminder-service-with-node-c05047befec3
doc: https://redis.io/topics/notifications (xE bayrağını arayın)
Sen kullanabilirsiniz Sıralama Set skoru olarak zaman damgası ile TTL kabı almak için REDIS içinde. Örneğin, kümeye bir olay dizisi eklediğinizde, puanını olay saatine ayarlayabilirsiniz. Böylece herhangi bir zaman aralığının verilerini arayarak alabilirsiniz.
zrangebyscore "your set name" min-time max-time
Dahası, zremrangebyscore "your set name" min-time max-time
eski olayları kaldırmak için kullanarak zaman aşımına uğrayabiliriz .
Buradaki tek dezavantaj, setin boyutunu korumak için dışarıdan bir süreçten temizlik yapmanız gerektiğidir.
Sen edebilirsiniz sona kolaylığı Redis karmaları, Ör kullanarak piton
import redis
conn = redis.Redis('localhost')
conn.hmset("hashed_user", {'name': 'robert', 'age': 32})
conn.expire("hashed_user", 10)
Bu, tüm sona erecek çocuk anahtarlarını içinde karma hashed_user 10 saniye sonra
redis-cli ile aynı,
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 saniye sonra
127.0.0.1:6379> hgetall testt
(empty list or set)
hset
tam değil çocuk süresinin dolması ile ilgili hset
.