Answers:
为了使Redis保持简单,这是不可能的。
Redis的创建者Quoth Antirez:
嗨,不可能为该特定字段使用其他顶级密钥,或者与具有过期时间的另一个字段一起存储,同时获取两者,并让应用程序根据以下内容了解它是否仍然有效:当前时间。
Redis不支持使用TTL
除顶级密钥以外的其他哈希,哈希将使整个哈希失效。如果使用分片群集,则可以使用另一种方法。这种方法并非在所有情况下都有用,并且性能特征可能与预期的有所不同。仍然值得一提:
当具有哈希时,该结构基本上如下所示:
hash_top_key
- child_key_1 -> some_value
- child_key_2 -> some_value
...
- child_key_n -> some_value
由于我们要添加TTL
到子键,因此可以将其移到顶部键。要点是,密钥现在应该是hash_top_key
和子密钥的组合:
{hash_top_key}child_key_1 -> some_value
{hash_top_key}child_key_2 -> some_value
...
{hash_top_key}child_key_n -> some_value
我们{}
故意使用该符号。这使所有这些键都落入相同的位置hash slot
。您可以在此处了解更多信息:https : //redis.io/topics/cluster-tutorial
现在,如果我们要执行相同的哈希操作,则可以执行以下操作:
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
这里有趣的是HGETALL
。首先,我们hash slot
为所有孩子的钥匙买了钥匙。然后,我们获取该特定项的密钥hash slot
,最后获取值。我们在这里需要小心,因为可能有更多的n
键,hash slot
并且可能还有一些我们不感兴趣但它们具有相同键的键hash slot
。实际上,我们可以编写Lua
脚本来通过执行EVAL
or EVALSHA
命令在服务器中执行这些步骤。同样,您需要考虑这种方法在特定情况下的性能。
更多参考:
有一个Redisson java框架,该框架实现了Map
具有条目TTL支持的哈希对象。它在内部使用hmap
和zset
Redis对象。用法示例:
RMapCache<Integer, String> map = redisson.getMapCache('map');
map.put(1, 30, TimeUnit.DAYS); // this entry expires in 30 days
这种方法非常有用。
在作为Redis 分支的KeyDB中,这是可能的。因为它是Fork,所以它与Redis完全兼容,并且可以替代。
只需使用EXPIREMEMBER命令。它适用于集合,散列和排序集合。
EXPIREMEMBER键名子键[时间]
您还可以使用TTL和PTTL来查看到期时间
TTL键名子键
此处提供了更多文档:https : //docs.keydb.dev/docs/commands/#expiremember
关于NodeJS实现,我expiryTime
在保存在HASH中的对象中添加了一个自定义字段。然后,在特定时间段之后,我使用以下代码清除过期的HASH条目:
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
创建一个keys
从哈希表中删除数组,然后client.hdel(HASH_NAME, ...keys)
在一次调用中将其传递给的方式来提高效率。
const keys = Object.keys(reply).filter(key => reply[key] && JSON.parse(reply[key]).expiryTime < Date.now()); client.hdel(HASH_NAME, ...keys);
您可以。这是一个例子。
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
如果您想使散列中的特定密钥过期,则早于1个月。这是不可能的。Redis expire命令适用于哈希中的所有键。如果设置每日哈希密钥,则可以设置密钥生存时间。
hset key-20140325 f1 1
expire key-20140325 100
hset key-20140325 f1 2
您可以以不同的方式在Redis中存储键/值以实现此目的,只需在存储键时在键中添加前缀或名称空间即可,例如“ hset_”
获取GET hset_key
等于的键/值HGET hset key
添加SET hset_key value
等于的键/值HSET hset key
获取所有KEYS hset_*
等于HGETALL hset
获取所有值应在2个操作中完成,首先获取所有键,KEYS hset_*
然后获取每个键的值
使用TTL添加键/值或过期是问题所在:
SET hset_key value
EXPIRE hset_key
注意:KEYS
将在整个数据库中查找与之匹配的键,这可能会影响性能,尤其是在您拥有大型数据库的情况下。
注意:
KEYS
将在整个数据库中查找与之匹配的密钥,这可能会影响性能,尤其是在您拥有大型数据库的情况下。SCAN 0 MATCH hset_*
只要它不阻塞服务器,可能会更好,但是对于大数据库,性能仍然是一个问题。
您可以创建一个新的数据库,用于单独存储要过期的这些密钥,尤其是在密钥数量很少的情况下。
感谢@DanFarrell强调了与以下内容有关的性能问题
KEYS
hashset
..得到O(1)设置O(1)得到所有O(n)
scan 0 match namespace:*
只要不阻塞服务器,它可能会更好
您可以通过psubscribe
和使用Redis键空间通知"__keyevent@<DB-INDEX>__:expired"
。
这样,每次密钥过期时,您都会在redis连接上发布一条消息。
关于您的问题,基本上,您使用set
一个以s / ms为单位的到期时间来创建一个临时的“正常”密钥。它应与您要在集合中删除的密钥的名称匹配。
由于您的临时密钥将在"__keyevent@0__:expired"
过期时发布到您的redis连接中,因此您可以轻松地从原始集中删除密钥,因为消息中将包含密钥名称。
该页面上的一个简单示例:https : //medium.com/@micah1powell/using-redis-keyspace-notifications-for-a-reminder-service-with-node-c05047befec3
doc:https://redis.io/topics/notifications(查找xE标志)
您可以轻松地使Redis哈希过期,例如使用python
import redis
conn = redis.Redis('localhost')
conn.hmset("hashed_user", {'name': 'robert', 'age': 32})
conn.expire("hashed_user", 10)
这将过期的所有子键中的散列 hashed_user 10秒后
来自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"
10秒后
127.0.0.1:6379> hgetall testt
(empty list or set)
hset
孩子没满hset
。