Respuestas:
Esto no es posible , en aras de mantener Redis simple .
Quoth Antirez, creador de Redis:
Hola, no es posible, use una clave de nivel superior diferente para ese campo específico, o almacene junto con el archivo archivado otro campo con un tiempo de vencimiento, obtenga ambos y deje que la aplicación comprenda si aún es válida o no según tiempo actual.
Redis no admite tener TTL
hash que no sean la clave superior, que expiraría todo el hash. Si está utilizando un clúster fragmentado, existe otro enfoque que podría utilizar. Este enfoque podría no ser útil en todos los escenarios y las características de desempeño podrían diferir de las esperadas. Todavía vale la pena mencionar:
Al tener un hash, la estructura básicamente se ve así:
hash_top_key
- child_key_1 -> some_value
- child_key_2 -> some_value
...
- child_key_n -> some_value
Como queremos agregar TTL
a las claves secundarias, podemos moverlas a las claves superiores. El punto principal es que la clave ahora debería ser una combinación de una hash_top_key
clave secundaria:
{hash_top_key}child_key_1 -> some_value
{hash_top_key}child_key_2 -> some_value
...
{hash_top_key}child_key_n -> some_value
Estamos usando la {}
notación a propósito. Esto permite que todas esas llaves caigan en la misma hash slot
. Puede leer más sobre esto aquí: https://redis.io/topics/cluster-tutorial
Ahora bien, si queremos hacer la misma operación de hashes, podríamos hacer:
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
El interesante aquí es HGETALL
. Primero obtenemos las hash slot
claves para todos nuestros hijos. Luego obtenemos las claves para ese particular hash slot
y finalmente recuperamos los valores. Debemos tener cuidado aquí, ya que podría haber más que n
claves para eso hash slot
y también podría haber claves que no nos interesan pero tienen las mismas hash slot
. De hecho, podríamos escribir un Lua
script para realizar esos pasos en el servidor ejecutando un comando EVAL
o EVALSHA
. Nuevamente, debe tener en cuenta el rendimiento de este enfoque para su escenario particular.
Algunas referencias más:
Existe un marco Java de Redisson que implementa un Map
objeto hash con soporte TTL de entrada. Utiliza hmap
y zset
Redis objetos debajo del capó. Ejemplo de uso:
RMapCache<Integer, String> map = redisson.getMapCache('map');
map.put(1, 30, TimeUnit.DAYS); // this entry expires in 30 days
Este enfoque es bastante útil.
Esto es posible en KeyDB, que es una bifurcación de Redis. Debido a que es un Fork, es totalmente compatible con Redis y funciona como un reemplazo directo.
Simplemente use el comando EXPIREMEMBER. Funciona con conjuntos, hashes y conjuntos ordenados.
EXPIREMEMBER subclave de nombre clave [hora]
También puede usar TTL y PTTL para ver el vencimiento
Subclave de nombre de clave TTL
Más documentación está disponible aquí: https://docs.keydb.dev/docs/commands/#expiremember
Con respecto a la implementación de NodeJS, agregué un expiryTime
campo personalizado en el objeto que guardo en el HASH. Luego, después de un período de tiempo específico, borro las entradas HASH caducadas usando el siguiente código:
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
para crear una matriz de keys
para eliminar del hash y luego pasar eso client.hdel(HASH_NAME, ...keys)
en una sola llamada.
const keys = Object.keys(reply).filter(key => reply[key] && JSON.parse(reply[key]).expiryTime < Date.now()); client.hdel(HASH_NAME, ...keys);
Usted puede. Aquí hay un ejemplo.
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
Uso EXPIRE o EXPIREAT comando.
Si desea caducar claves específicas en el hash de más de 1 mes. Esto no es posible. El comando Redis expire es para todas las claves en el hash. Si establece una clave hash diaria, puede establecer un tiempo de vida de las claves.
hset key-20140325 f1 1
expire key-20140325 100
hset key-20140325 f1 2
Puede almacenar claves / valores en Redis de manera diferente para lograr esto, simplemente agregando un prefijo o espacio de nombres a sus claves cuando las almacena, por ejemplo, "hset_"
Obtener una clave / valor GET hset_key
igual aHGET hset key
Agregar una clave / valor SET hset_key value
igual aHSET hset key
Obtener todas las claves KEYS hset_*
iguales aHGETALL hset
Obtener todos los valores debe hacerse en 2 operaciones, primero obtenga todas las claves y KEYS hset_*
luego obtenga el valor para cada clave
Agregue una clave / valor con TTL o expire, que es el tema de la pregunta:
SET hset_key value
EXPIRE hset_key
Nota : KEYS
buscará coincidir con la clave en toda la base de datos, lo que puede afectar el rendimiento, especialmente si tiene una gran base de datos.
Nota:
KEYS
buscará coincidir con la clave en toda la base de datos, lo que puede afectar el rendimiento, especialmente si tiene una gran base de datos. aunque SCAN 0 MATCH hset_*
podría ser mejor siempre que no bloquee el servidor, pero el rendimiento sigue siendo un problema en el caso de una gran base de datos.
Puede crear una nueva base de datos para almacenar por separado estas claves que desea que caduquen, especialmente si son un pequeño conjunto de claves.
Gracias a @DanFarrell, quien destacó el problema de rendimiento relacionado con
KEYS
hashset
... obtener O (1) establecer O (1) obtener todas O (n)
O(n)
para varias cosas en el conjunto, KEYS
para varias cosas en la base de datos.
scan 0 match namespace:*
podría ser mejor siempre y cuando no bloquee el servidor
Tuvimos el mismo problema discutido aquí.
Tenemos un hash de Redis, una clave para las entradas de hash (pares de nombre / valor), y necesitábamos mantener tiempos de vencimiento individuales en cada entrada de hash.
Implementamos esto agregando n bytes de datos de prefijo que contienen información de caducidad codificada cuando escribimos los valores de entrada de hash, también configuramos la clave para que caduque en el momento contenido en el valor que se escribe.
Luego, al leer, decodificamos el prefijo y verificamos su vencimiento. Esto es una sobrecarga adicional, sin embargo, las lecturas siguen siendo O (n) y la clave completa caducará cuando haya caducado la última entrada hash.
Puede usar las notificaciones del espacio de claves de Redis usando psubscribe
y "__keyevent@<DB-INDEX>__:expired"
.
Con eso, cada vez que caduque una clave, recibirá un mensaje publicado en su conexión redis.
Con respecto a su pregunta, básicamente, crea una clave "normal" temporal set
con un tiempo de vencimiento en s / ms. Debe coincidir con el nombre de la clave que desea eliminar en su conjunto.
Como su clave temporal se publicará en su conexión de redis manteniendo el "__keyevent@0__:expired"
cuando expire, puede eliminar fácilmente su clave de su conjunto original ya que el mensaje tendrá el nombre de la clave.
Un ejemplo sencillo en la práctica en esa página: https://medium.com/@micah1powell/using-redis-keyspace-notifications-for-a-reminder-service-with-node-c05047befec3
doc: https://redis.io/topics/notifications (busque la bandera xE)
Puede utilizar Sorted Set en redis para obtener un contenedor TTL con marca de tiempo como puntuación. Por ejemplo, cada vez que inserta una cadena de evento en el conjunto, puede establecer su puntuación en la hora del evento. Por lo tanto, puede obtener datos de cualquier ventana de tiempo llamando
zrangebyscore "your set name" min-time max-time
Además, podemos caducar utilizando zremrangebyscore "your set name" min-time max-time
para eliminar eventos antiguos.
El único inconveniente aquí es que tienes que hacer la limpieza desde un proceso externo para mantener el tamaño del conjunto.
Puede caducar los hash de Redis con facilidad, por ejemplo, usando python
import redis
conn = redis.Redis('localhost')
conn.hmset("hashed_user", {'name': 'robert', 'age': 32})
conn.expire("hashed_user", 10)
Esto expirará todas las claves secundarias en hash hashed_user después de 10 segundos
lo mismo de 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"
después de 10 segundos
127.0.0.1:6379> hgetall testt
(empty list or set)
hset
niño expira, no el completo hset
.