Antworten:
Dies ist nicht möglich , um Redis einfach zu halten .
Quoth Antirez, Schöpfer von Redis:
Hallo, es ist nicht möglich, entweder einen anderen Schlüssel der obersten Ebene für dieses bestimmte Feld zu verwenden oder zusammen mit dem abgelegten anderen Feld mit einer Ablaufzeit zu speichern, beide abzurufen und der Anwendung zu erklären, ob sie noch gültig ist oder nicht aktuelle Uhrzeit.
Redis unterstützt es nicht, TTL
andere Hashes als den oberen Schlüssel zu verwenden, wodurch der gesamte Hash abläuft. Wenn Sie einen Sharded-Cluster verwenden, können Sie einen anderen Ansatz verwenden. Dieser Ansatz ist möglicherweise nicht in allen Szenarien nützlich, und die Leistungsmerkmale können von den erwarteten abweichen. Noch erwähnenswert:
Wenn Sie einen Hash haben, sieht die Struktur im Grunde so aus:
hash_top_key
- child_key_1 -> some_value
- child_key_2 -> some_value
...
- child_key_n -> some_value
Da wir die untergeordneten TTL
Schlüssel hinzufügen möchten , können wir sie in die oberen Schlüssel verschieben. Der Hauptpunkt ist, dass der Schlüssel jetzt eine Kombination aus einem hash_top_key
untergeordneten Schlüssel sein sollte:
{hash_top_key}child_key_1 -> some_value
{hash_top_key}child_key_2 -> some_value
...
{hash_top_key}child_key_n -> some_value
Wir verwenden die {}
Notation absichtlich. Dadurch können alle diese Schlüssel in dieselbe fallen hash slot
. Weitere Informationen finden Sie hier: https://redis.io/topics/cluster-tutorial
Wenn wir nun die gleiche Operation von Hashes ausführen möchten, können wir Folgendes tun:
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
Das Interessante hier ist HGETALL
. Zuerst bekommen wir die hash slot
Schlüssel für alle unsere Kinder. Dann bekommen wir die Schlüssel für diesen bestimmten hash slot
und schließlich rufen wir die Werte ab. Wir müssen hier vorsichtig sein, da es dafür mehr als nur n
Schlüssel geben kann hash slot
und es auch Schlüssel geben kann, an denen wir nicht interessiert sind, die aber dieselben haben hash slot
. Wir könnten tatsächlich ein Lua
Skript schreiben , um diese Schritte auf dem Server auszuführen, indem wir einen Befehl EVAL
oder ausführen EVALSHA
. Auch hier müssen Sie die Leistung dieses Ansatzes für Ihr spezielles Szenario berücksichtigen.
Einige weitere Referenzen:
Es gibt ein Redisson- Java-Framework, das Hash- Map
Objekte mit TTL-Unterstützung für Einträge implementiert . Es verwendet hmap
und zset
Redis Objekte unter der Haube. Anwendungsbeispiel:
RMapCache<Integer, String> map = redisson.getMapCache('map');
map.put(1, 30, TimeUnit.DAYS); // this entry expires in 30 days
Dieser Ansatz ist sehr nützlich.
Dies ist in KeyDB möglich, einer Fork of Redis. Da es sich um eine Gabel handelt, ist sie vollständig mit Redis kompatibel und fungiert als Ersatz.
Verwenden Sie einfach den Befehl EXPIREMEMBER. Es funktioniert mit Sets, Hashes und sortierten Sets.
EXPIREMEMBER-Keyname-Unterschlüssel [Zeit]
Sie können auch TTL und PTTL verwenden, um den Ablauf anzuzeigen
TTL-Keyname-Unterschlüssel
Weitere Dokumentation finden Sie hier: https://docs.keydb.dev/docs/commands/#expiremember
In Bezug auf eine NodeJS-Implementierung habe ich expiryTime
dem Objekt, das ich im HASH speichere, ein benutzerdefiniertes Feld hinzugefügt. Nach einer bestimmten Zeit lösche ich die abgelaufenen HASH-Einträge mit dem folgenden Code:
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
ein Array keys
zum Löschen aus dem Hash erstellen und dieses dann client.hdel(HASH_NAME, ...keys)
in einem einzigen Aufruf an übergeben.
const keys = Object.keys(reply).filter(key => reply[key] && JSON.parse(reply[key]).expiryTime < Date.now()); client.hdel(HASH_NAME, ...keys);
Sie können. Hier ist ein Beispiel.
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
Verwenden Sie den Befehl EXPIRE oder EXPIREAT .
Wenn Sie bestimmte Schlüssel im Hash ablaufen lassen möchten, die älter als 1 Monat sind. Das ist nicht möglich. Der Redis Expire-Befehl gilt für alle Schlüssel im Hash. Wenn Sie den täglichen Hash-Schlüssel festlegen, können Sie die Lebensdauer der Schlüssel festlegen.
hset key-20140325 f1 1
expire key-20140325 100
hset key-20140325 f1 2
Sie können Schlüssel / Werte in Redis anders speichern, um dies zu erreichen, indem Sie Ihren Schlüsseln einfach ein Präfix oder einen Namespace hinzufügen, wenn Sie sie speichern, z. B. "hset_".
Holen Sie sich einen Schlüssel / Wert GET hset_key
gleichHGET hset key
Fügen Sie einen Schlüssel / Wert hinzu, der SET hset_key value
gleich istHSET hset key
Holen Sie sich alle Schlüssel KEYS hset_*
gleichHGETALL hset
Das Abrufen aller Werte sollte in 2 Operationen erfolgen. Holen Sie sich zuerst alle Schlüssel und KEYS hset_*
dann den Wert für jeden Schlüssel
Fügen Sie mit TTL einen Schlüssel / Wert hinzu oder verfallen, was das Thema der Frage ist:
SET hset_key value
EXPIRE hset_key
Hinweis : KEYS
Sucht nach Übereinstimmungen mit dem Schlüssel in der gesamten Datenbank, was sich auf die Leistung auswirken kann, insbesondere wenn Sie über eine große Datenbank verfügen.
Hinweis:
KEYS
sucht nach Übereinstimmungen mit dem Schlüssel in der gesamten Datenbank, was sich auf die Leistung auswirken kann, insbesondere wenn Sie über eine große Datenbank verfügen. Dies ist SCAN 0 MATCH hset_*
möglicherweise besser, solange der Server nicht blockiert wird, die Leistung jedoch bei großen Datenbanken ein Problem darstellt.
Sie können eine neue Datenbank erstellen, um diese Schlüssel, die Sie ablaufen lassen möchten, separat zu speichern, insbesondere wenn es sich um kleine Schlüsselsätze handelt.
Vielen Dank an @DanFarrell, der das Leistungsproblem im Zusammenhang mit hervorgehoben hat
KEYS
hashset
.. get O (1) set O (1) get all O (n)
O(n)
für die Anzahl der Dinge in der Menge und KEYS
für die Anzahl der Dinge in der Datenbank .
scan 0 match namespace:*
könnte besser sein, solange es den Server nicht blockiert
Wir hatten das gleiche Problem hier diskutiert.
Wir haben einen Redis-Hash, einen Schlüssel für Hash-Einträge (Name / Wert-Paare), und wir mussten für jeden Hash-Eintrag individuelle Ablaufzeiten festlegen.
Wir haben dies implementiert, indem wir beim Schreiben der Hash-Eintragswerte n Bytes Präfixdaten hinzugefügt haben, die codierte Ablaufinformationen enthalten. Außerdem haben wir den Schlüssel so festgelegt, dass er zu dem Zeitpunkt abläuft, der in dem zu schreibenden Wert enthalten ist.
Dann dekodieren wir beim Lesen das Präfix und prüfen, ob es abgelaufen ist. Dies ist ein zusätzlicher Aufwand, die Lesevorgänge sind jedoch immer noch O (n) und der gesamte Schlüssel läuft ab, wenn der letzte Hash-Eintrag abgelaufen ist.
Sie können die Redis Keyspace-Benachrichtigungen mit psubscribe
und verwenden "__keyevent@<DB-INDEX>__:expired"
.
Damit erhalten Sie jedes Mal, wenn ein Schlüssel abläuft, eine Nachricht, die auf Ihrer Redis-Verbindung veröffentlicht wird.
In Bezug auf Ihre Frage erstellen Sie im Grunde einen temporären "normalen" Schlüssel set
mit einer Ablaufzeit in s / ms. Es sollte mit dem Namen des Schlüssels übereinstimmen, den Sie in Ihrem Set löschen möchten.
Da Ihr temporärer Schlüssel in Ihrer Redis-Verbindung veröffentlicht wird, "__keyevent@0__:expired"
wenn er abgelaufen ist, können Sie Ihren Schlüssel einfach aus Ihrem ursprünglichen Satz löschen, da die Nachricht den Namen des Schlüssels enthält.
Ein einfaches Beispiel in der Praxis auf dieser Seite: https://medium.com/@micah1powell/using-redis-keyspace-notifications-for-a-reminder-service-with-node-c05047befec3
doc: https://redis.io/topics/notifications (achten Sie auf das Flag xE)
Sie können Sorted Set in redis verwenden, um einen TTL-Container mit Zeitstempel als Punktzahl zu erhalten. Wenn Sie beispielsweise eine Ereigniszeichenfolge in den Satz einfügen, können Sie die Punktzahl auf die Ereigniszeit festlegen. So können Sie durch Aufrufen Daten aus jedem Zeitfenster abrufen
zrangebyscore "your set name" min-time max-time
Darüber hinaus können wir verfallen, indem wir zremrangebyscore "your set name" min-time max-time
alte Ereignisse entfernen.
Der einzige Nachteil hierbei ist, dass Sie die Reinigung von einem Außenstehenden durchführen müssen, um die Größe des Sets beizubehalten.
Sie können Redis-Hashes problemlos ablaufen lassen , z. B. mit Python
import redis
conn = redis.Redis('localhost')
conn.hmset("hashed_user", {'name': 'robert', 'age': 32})
conn.expire("hashed_user", 10)
Dadurch laufen alle untergeordneten Schlüssel in hash hashed_user nach 10 Sekunden ab
das gleiche von 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"
nach 10 Sekunden
127.0.0.1:6379> hgetall testt
(empty list or set)
hset
Kind nicht die volle hset
.