如何在redis中“扩展”“HSET”子键?

问题描述 投票:71回答:9

我需要使用redis散列中的所有密钥到期,这些密钥早于1个月。

hash redis
9个回答
91
投票

This is not possible,为了keeping Redis simple

Quis Antirez,Redis的创造者:

嗨,这是不可能的,要么为该特定字段使用不同的顶级密钥,要么与提交的另一个字段一起存储过期时间,同时获取两者,并让应用程序了解它是否仍然有效当前时间。


3
投票

有一个Redisson java框架,它实现了具有入口TTL支持的哈希Map对象。它使用引擎盖下的hmapzset Redis对象。用法示例:

RMapCache<Integer, String> map = redisson.getMapCache('map');
map.put(1, 30, TimeUnit.DAYS); // this entry expires in 30 days

这种方法非常有用。


1
投票

关于NodeJS实现,我在HASH中保存的对象中添加了自定义expiryTime字段。然后在一段特定的时间后,我使用以下代码清除过期的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);
            }
        })
    }
});

1
投票

您可以通过不同方式存储Redis中的键/值来实现此目的,只需在存储键时为键添加前缀或命名空间即可。 “hset_”

  • 得到一个键/值GET hset_key等于HGET hset key
  • 添加键/值SET hset_key value等于HSET hset key
  • 得到所有键KEYS hset_*等于HGETALL hset
  • 获取所有值应该在2个操作中完成,首先获取所有键qazxsw poi然后获取每个键的值
  • 使用TTL或expire添加键/值是问题的主题:
KEYS hset_*

注意: SET hset_key value EXPIRE hset_key 将查找匹配整个数据库中的密钥,这可能会影响性能,尤其是如果您有大数据库。

注意:

  • KEYS将查找匹配整个数据库中的密钥,这可能会影响性能,尤其是如果您有大数据库。 KEYS可能会更好,只要它不阻止服务器,但在大数据库的情况下性能仍然是一个问题。
  • 您可以创建一个新数据库,用于单独存储您希望过期的密钥,特别是如果它们是一组小密钥。

感谢@DanFarrell,他强调了与SCAN 0 MATCH hset_*相关的性能问题


1
投票

Redis不支持在除顶键之外的哈希上使用KEYS,这会使整个哈希值到期。如果您使用的是分片群集,则可以使用另一种方法。这种方法在所有情况下都没有用,性能特征可能与预期的不同。还是值得一提的是:

有哈希时,结构基本上如下:

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脚本,通过执行LuaEVAL命令在服务器中执行这些步骤。同样,您需要考虑针对您的特定方案的此方法的性能。

更多参考资料:


0
投票

您可以。这是一个例子。

https://redis.io/commands/eval

使用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 EXPIRE命令。

如果您希望在超过1个月的哈希值中使特定键失效。这是不可能的。 Redis expire命令用于散列中的所有键。如果设置每日哈希键,则可以设置密钥生存时间。

EXPIREAT

0
投票

你可以轻松过期Redis哈希,例如使用python

hset key-20140325 f1 1
expire key-20140325 100
hset key-20140325 f1 2

这将在10秒后使散列hashed_user中的所有子键失效

同样来自redis-cli,

import redis
conn = redis.Redis('localhost')
conn.hmset("hashed_user", {'name': 'robert', 'age': 32})
conn.expire("hashed_user", 10)

10秒后

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"

0
投票

您可以使用127.0.0.1:6379> hgetall testt (empty list or set) psubscribe来使用Redis Keyspace Notifications。

这样,每次密钥到期时,您都会在redis连接上发布消息。

关于你的问题基本上你使用"__keyevent@<DB-INDEX>__:expired"创建一个临时的“正常”密钥,其过期时间为s / ms。它应该与您要在集合中删除的密钥的名称相匹配。

由于临时密钥将在过期时发布到持有set的redis连接,因此您可以轻松地从原始密钥中删除密钥,因为邮件将具有密钥的名称。

该页面上的一个简单例子:"__keyevent@0__:expired"

doc:https://medium.com/@micah1powell/using-redis-keyspace-notifications-for-a-reminder-service-with-node-c05047befec3(寻找旗帜xE)


0
投票

您可以在redis中使用Sorted Set来获取时间戳为分数的TTL容器。例如,每当您将事件字符串插入集合时,您都可以将其分数设置为事件时间。因此,您可以通过调用https://redis.io/topics/notifications获取任何时间窗口的数据

此外,我们可以通过使用zrangebyscore "your set name" min-time max-time删除旧事件来到期。

这里唯一的缺点是你必须从局外人进程做家务,以保持集合的大小。

© www.soinside.com 2019 - 2024. All rights reserved.