Odpowiedzi:
Nie jest to możliwe ze względu na prostotę obsługi Redis .
Quoth Antirez, twórca Redis:
Cześć, nie jest możliwe, użyj innego klucza najwyższego poziomu dla tego konkretnego pola lub zapisz wraz z polem inne pole z czasem wygaśnięcia, pobierz oba i pozwól aplikacji zrozumieć, czy jest nadal ważny, czy nie jest oparty na Obecny czas.
Redis nie obsługuje TTL
haszów innych niż górny klucz, co spowodowałoby wygaśnięcie całego skrótu. Jeśli używasz podzielonego na fragmenty klastra, możesz zastosować inne podejście. To podejście nie może być przydatne we wszystkich scenariuszach, a charakterystyki wydajności mogą różnić się od oczekiwanych. Nadal warto wspomnieć:
W przypadku skrótu struktura zasadniczo wygląda następująco:
hash_top_key
- child_key_1 -> some_value
- child_key_2 -> some_value
...
- child_key_n -> some_value
Ponieważ chcemy dodać TTL
klucze podrzędne, możemy przenieść je do kluczy górnych. Najważniejsze jest to, że klucz powinien być teraz kombinacją hash_top_key
klucza podrzędnego:
{hash_top_key}child_key_1 -> some_value
{hash_top_key}child_key_2 -> some_value
...
{hash_top_key}child_key_n -> some_value
Celowo używamy {}
notacji. Dzięki temu wszystkie te klucze wchodzą w to samo hash slot
. Możesz przeczytać więcej na ten temat tutaj: https://redis.io/topics/cluster-tutorial
Teraz, jeśli chcemy wykonać tę samą operację haszowania, możemy zrobić:
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
Interesujący jest tutaj HGETALL
. Najpierw otrzymujemy hash slot
klucze dla wszystkich naszych dzieci. Następnie otrzymujemy klucze do tego konkretnego hash slot
i ostatecznie pobieramy wartości. Musimy być tutaj ostrożni, ponieważ może być do tego coś więcej niż tylko n
klucze, hash slot
a także mogą być klucze, które nas nie interesują, ale mają takie same hash slot
. Moglibyśmy właściwie napisać Lua
skrypt, który wykonałby te kroki na serwerze, wykonując polecenie EVAL
lub EVALSHA
. Ponownie musisz wziąć pod uwagę wydajność tego podejścia w konkretnym scenariuszu.
Więcej odniesień:
Istnieje framework java Redisson , który implementuje Map
obiekt skrótu z obsługą TTL wejścia. Używa hmap
i zset
obiektów Redis pod maską. Przykład użycia:
RMapCache<Integer, String> map = redisson.getMapCache('map');
map.put(1, 30, TimeUnit.DAYS); // this entry expires in 30 days
To podejście jest całkiem przydatne.
Jest to możliwe w KeyDB, który jest Fork of Redis. Ponieważ jest to Fork, jest w pełni kompatybilny z Redis i działa jako kropla w zastępstwie.
Po prostu użyj polecenia EXPIREMEMBER. Działa z zestawami, skrótami i posortowanymi zestawami.
EXPIREMEMBER podklucz nazwy klucza [czas]
Możesz także użyć TTL i PTTL, aby zobaczyć datę ważności
Podklucz nazwy klucza TTL
Więcej dokumentacji można znaleźć tutaj: https://docs.keydb.dev/docs/commands/#expiremember
Jeśli chodzi o implementację NodeJS, dodałem niestandardowe expiryTime
pole w obiekcie, który zapisuję w HASH. Następnie po określonym czasie usuwam wygasłe wpisy HASH za pomocą następującego kodu:
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
do utworzenia tablicy keys
do usunięcia z skrótu, a następnie przekazania jej client.hdel(HASH_NAME, ...keys)
w jednym wywołaniu.
const keys = Object.keys(reply).filter(key => reply[key] && JSON.parse(reply[key]).expiryTime < Date.now()); client.hdel(HASH_NAME, ...keys);
Możesz. Oto przykład.
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
Zastosowanie EXPIRE lub EXPIREAT poleceń.
Jeśli chcesz wygasnąć określone klucze w skrócie starsze niż 1 miesiąc. To jest niemożliwe. Polecenie Redis expire dotyczy wszystkich kluczy w skrócie. Jeśli ustawisz dzienny klucz skrótu, możesz ustawić czas życia kluczy.
hset key-20140325 f1 1
expire key-20140325 100
hset key-20140325 f1 2
Aby to osiągnąć, możesz przechowywać klucze / wartości w Redis w inny sposób, po prostu dodając przedrostek lub przestrzeń nazw do kluczy podczas ich przechowywania, np. „Hset_”
Uzyskaj klucz / wartość GET hset_key
równąHGET hset key
Dodaj klucz / wartość SET hset_key value
równa sięHSET hset key
Pobierz wszystkie klucze KEYS hset_*
równa sięHGETALL hset
Pobieranie wszystkich wartości powinno odbywać się w 2 operacjach, najpierw pobierz wszystkie klucze, KEYS hset_*
a następnie uzyskaj wartość dla każdego klucza
Dodaj klucz / wartość z TTL lub wygaś, co jest tematem pytania:
SET hset_key value
EXPIRE hset_key
Uwaga : KEYS
sprawdzi dopasowanie klucza w całej bazie danych, co może mieć wpływ na wydajność, zwłaszcza jeśli masz dużą bazę danych.
Uwaga:
KEYS
wyszuka dopasowanie klucza w całej bazie danych, co może mieć wpływ na wydajność, zwłaszcza jeśli masz dużą bazę danych. chociaż SCAN 0 MATCH hset_*
może być lepszy, o ile nie blokuje serwera, ale nadal problemem jest wydajność w przypadku dużej bazy danych.
Możesz utworzyć nową bazę danych do oddzielnego przechowywania tych kluczy, które mają wygasnąć, zwłaszcza jeśli są to małe zestawy kluczy.
Podziękowania dla @DanFarrell, który zwrócił uwagę na problem związany z wydajnością
KEYS
hashset
.. get O (1) zestaw O (1) uzyskać wszystkie O (n)
O(n)
do liczby rzeczy w zestawie, KEYS
do liczby rzeczy w DB.
scan 0 match namespace:*
może być lepiej, o ile nie blokuje serwera
Omówiliśmy tutaj ten sam problem.
Mamy hash Redis, klucz do wpisów hash (pary nazwa / wartość) i musieliśmy przechowywać indywidualne czasy wygaśnięcia dla każdego wpisu hash.
Zaimplementowaliśmy to dodając n bajtów danych prefiksowych zawierających zakodowane informacje o wygaśnięciu, kiedy piszemy wartości wejściowe skrótu, ustawiliśmy również klucz tak, aby wygasał w momencie zawartym w zapisywanej wartości.
Następnie podczas czytania dekodujemy prefiks i sprawdzamy, czy wygasł. Jest to dodatkowe obciążenie, jednak odczyty są nadal O (n), a cały klucz wygaśnie po wygaśnięciu ostatniego wpisu skrótu.
Możesz użyć powiadomień Redis Keyspace przy użyciu psubscribe
i "__keyevent@<DB-INDEX>__:expired"
.
Dzięki temu za każdym razem, gdy klucz wygaśnie, otrzymasz wiadomość opublikowaną na Twoim połączeniu redis.
Jeśli chodzi o twoje pytanie, w zasadzie tworzysz tymczasowy „normalny” klucz set
z czasem wygaśnięcia w s / ms. Powinien pasować do nazwy klucza, który chcesz usunąć ze swojego zestawu.
Ponieważ twój tymczasowy klucz zostanie opublikowany w twoim połączeniu redis, które posiada, "__keyevent@0__:expired"
kiedy wygasł, możesz łatwo usunąć swój klucz z oryginalnego zestawu, ponieważ wiadomość będzie miała nazwę klucza.
Prosty przykład w praktyce na tej stronie: https://medium.com/@micah1powell/using-redis-keyspace-notifications-for-a-reminder-service-with-node-c05047befec3
doc: https://redis.io/topics/notifications (poszukaj flagi xE)
Możesz użyć sortowanego zestawu w redis, aby uzyskać kontener TTL z sygnaturą czasową jako wynikiem. Na przykład za każdym razem, gdy wstawisz ciąg zdarzenia do zestawu, możesz ustawić jego wynik na czas zdarzenia. W ten sposób możesz uzyskać dane z dowolnego okna czasu, dzwoniąc
zrangebyscore "your set name" min-time max-time
Co więcej, możemy wygasnąć, używając zremrangebyscore "your set name" min-time max-time
do usuwania starych wydarzeń.
Jedyną wadą jest to, że musisz robić porządki z zewnętrznego procesu, aby utrzymać rozmiar zestawu.
Można wygasają mieszań Redis w swobodnie, na przykład za pomocą python
import redis
conn = redis.Redis('localhost')
conn.hmset("hashed_user", {'name': 'robert', 'age': 32})
conn.expire("hashed_user", 10)
Spowoduje to wygaśnięcie wszystkich kluczy podrzędnych w hash hashed_user po 10 sekundach
to samo z 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"
po 10 sekundach
127.0.0.1:6379> hgetall testt
(empty list or set)
hset
dziecka nie do końca hset
.