Redis'de "HSET" alt anahtarının "SÜRESİ DOLDURULUR"?


108

1 aydan daha eski olan redis hash'deki tüm anahtarların kullanım sürelerini sona erdirmem gerekiyor.

Yanıtlar:


117

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.


8
bu nedenle redis harika bir yazılım parçasıdır. nerede basit
tutacaklarını biliyorlar

20

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

TTLAlt anahtarlara eklemek istediğimizden , bunları üst tuşlara taşıyabiliriz. Asıl nokta, anahtarın artık bir hash_top_keyalt 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 slottüm çocuklarımızın anahtarlarını alıyoruz. Sonra o belirli anahtarın anahtarlarını hash slotalırız ve sonunda değerleri alırız. Burada nanahtarlardan daha fazlası olabileceğinden hash slotve ilgilenmediğimiz anahtarlar da olabileceği için burada dikkatli olmamız gerekiyor ama aynı anahtarlara sahip hash slot. LuaBir EVALveya EVALSHAkomutunu ç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:


Bu yaklaşım, sona erme süreli basit anahtarlardan daha fazla bellek kullanır.
VasileM

3

Giriş TTL desteği ile hash nesnesini uygulayan bir Redisson java çerçevesi vardır Map. Kaputun altındaki nesneleri kullanır hmapve zsetRedis. 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.


ama nasıl harita oluşturabilirsiniz? çünkü herhangi bir öğretici veya oluştur / ayarla yöntemi
bulamıyorum

@ ZoltánNémeth Redis haritasında ilk değer eklendiğinde otomatik olarak oluşturulur.
Nikita Koksharov

3

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


2

Bir NodeJS uygulamasıyla ilgili olarak, HASH'e expiryTimekaydettiğ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);
            }
        })
    }
});

Bunu , hash'den silmek Array.filteriçin bir dizi oluşturmak için kullanarak ve keysardından bunu client.hdel(HASH_NAME, ...keys)tek bir çağrıda ileterek daha verimli hale getirebilirsiniz .
2019

const keys = Object.keys(reply).filter(key => reply[key] && JSON.parse(reply[key]).expiryTime < Date.now()); client.hdel(HASH_NAME, ...keys);
doublesharp

1

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

24
Karma içerisindeki tüm anahtarların süresinin dolmasını istediğini sanmıyorum , karma içindeki 1 aydan daha eski olan tüm anahtarlar , yani sadece bazı anahtarlar . Hangi AFAIK mümkün değil.
UpTheCreek

1
IMHO sorusu şunu varsayalım. Yani Jonathan benden +1 aldı, çünkü bana yardım etti! Thanx!
longliveenduro

"f1" ve "f2" nin geçerlilik süresi nasıl doluyor?
vgoklani

4
Bu soruya cevap vermiyor veya hiç yardımcı olmuyor. İhtiyaç, karmanın kendisinin değil, karmadaki öğelerin süresinin dolmasıdır.
Ron

@UpTheCreek Teşekkürler!
Jonathan Kim

1

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 : KEYSAnahtarı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


1
bunun performans özelliklerinde önemli bir değişiklik olduğunu unutmayın
Daniel Farrell

Nasıl! Zaman karmaşıklığı hakkında konuşurken bile, tüm bu işlemler aynı zaman karmaşıklık var hashset.. olsun O (1) ayarlanan O (1) Tüm O (n) olsun
Muhammed Soliman

"ANAHTARLARI yalnızca üretim ortamlarında çok dikkatli kullanılması gereken bir komut olarak düşünün." redis.io/commands/KEYS . HGETALL, kümedeki O(n)şeylerin sayısı, DB'deki şeylerin KEYSsayısı içindir.
Daniel Farrell

bu doğru, scan 0 match namespace:*sunucuyu engellemediği sürece daha iyi olabilir
Muhammad Soliman

1
ayrıca, bu anahtarları, eğer küçükse, farklı veritabanlarına ayırın. teşekkürler @DanFarrell
Muhammad Soliman

1

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.


0

Redis Keyspace Bildirimlerini psubscribeve 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)


0

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-timeeski 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.


-1

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)

7
soru hsettam değil çocuk süresinin dolması ile ilgili hset.
thangdc94

sorulan soruya cevap vermiyor
peteclark3
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.