Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Hash 如何";“到期”;";HSET“;redis中的子密钥?_Hash_Redis - Fatal编程技术网

Hash 如何";“到期”;";HSET“;redis中的子密钥?

Hash 如何";“到期”;";HSET“;redis中的子密钥?,hash,redis,Hash,Redis,为了安全起见,我需要使redis哈希中的所有密钥过期,这些密钥的过期时间超过1个月。 Redis的创造者安提雷斯说: 嗨,这是不可能的,或者使用不同的顶级键 特定字段,或与该字段一起存储另一个带有 过期时间,获取两者,并让应用程序了解它是否过期 仍然有效或不基于当前时间 你可以。这里有一个例子 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哈希中的所有密钥过期,这些密钥的过期时间超过1个月。

Redis的创造者安提雷斯说:

嗨,这是不可能的,或者使用不同的顶级键 特定字段,或与该字段一起存储另一个带有 过期时间,获取两者,并让应用程序了解它是否过期 仍然有效或不基于当前时间


你可以。这里有一个例子

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
有一个java框架,它实现了hash
Map
对象,并支持条目TTL。它在引擎盖下使用
hmap
zset
Redis对象。用法示例:

RMapCache map=redisson.getMapCache('map');
地图。放置(1,30,时间单位。天);//此条目将在30天后过期

这种方法非常有用。

关于NodeJS实现,我在散列中保存的对象中添加了一个自定义的
expiryTime
字段。然后在特定的时间段后,我使用以下代码清除过期的哈希项:

client.hgetall(散列名称、函数(err、reply){
若有(答复){
Object.key(reply.forEach)(key=>{
if(reply[key]&&JSON.parse(reply[key]).expiryTime<(新日期).getTime()){
hdel(散列名称、密钥);
}
})
}
});

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

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> hgetall testt
(empty list or set)
与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)

为了实现这一点,您可以在Redis中以不同的方式存储键/值,只需在存储键时为它们添加前缀或命名空间,例如“hset\ux”

  • 获取一个键/值
    Get hset_key
    等于
    HGET hset key

  • 添加一个键/值
    SET hset_key value
    等于
    hset hset key

  • 获取所有钥匙
    keys hset.*
    等于
    HGETALL hset

  • 获取所有VAL应在2次操作中完成,首先获取所有键
    keys hset.*
    然后获取每个键的值

  • 添加带有TTL或expire的键/值,这是问题的主题:

注意
将在整个数据库中查找匹配的键,这可能会影响性能,尤其是当您的数据库很大时

注:

  • 密钥
    将在整个数据库中查找匹配的密钥,这可能会影响性能,尤其是在您有大型数据库的情况下。虽然
    SCAN 0 MATCH hset.*
    可能更好,只要它不阻塞服务器,但在大型数据库的情况下,性能仍然是一个问题

  • 您可以创建一个新的数据库,分别存储这些要过期的密钥,特别是当它们是一小组密钥时

感谢@DanFarrell,他强调了与


您可以通过使用
psubscribe
使用Redis键空间通知__keyevent@__:过期“

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

关于您的问题,基本上您可以使用
set
创建一个临时“正常”密钥,过期时间为s/ms。它应该与您希望在集合中删除的密钥的名称相匹配

因为您的临时密钥将被发布到您的redis连接中,并持有
“__keyevent@0__:expired“
当密钥过期时,您可以轻松地从原始密钥集中删除密钥,因为消息中将显示密钥的名称

在该页面上有一个简单的实践示例:


doc:(查找标志xE)

您可以在redis中使用排序集来获得一个带有时间戳作为分数的TTL容器。 例如,每当在集合中插入事件字符串时,都可以将其分数设置为事件时间。 因此,您可以通过调用
zrangebyscore“您的设置名称”最小时间最大时间

此外,我们可以通过使用
zremrangebyscore“yourset name”min time max time
删除旧事件来实现过期


这里唯一的缺点是您必须从一个外部进程进行内务处理,以保持集合的大小

Redis不支持将
TTL
放在除top键以外的散列上,这将使整个散列过期。如果您使用的是分片集群,那么可以使用另一种方法。这种方法不可能在所有场景中都有用,而且性能特征可能与预期的不同。仍然值得一提的是:

当有散列时,结构基本上如下所示:

hash_top_key
  - child_key_1 -> some_value
  - child_key_2 -> some_value
  ...
  - child_key_n -> some_value
由于我们希望将
TTL
添加到子键,因此可以将它们移动到顶部键。主要的一点是,现在的键应该是
散列\u top\u键
和子键的组合:

{hash_top_key}child_key_1 -> some_value
{hash_top_key}child_key_2 -> some_value
...
{hash_top_key}child_key_n -> some_value
我们故意使用
{}
符号。这允许所有这些键落在相同的
哈希槽中。您可以在此处阅读更多信息:

现在,如果我们想对哈希进行相同的操作,我们可以:

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
。首先,我们为所有子密钥获取
哈希槽。然后我们获取特定
哈希槽的键,最后我们检索值。在这里我们需要小心,因为对于
散列槽
,可能有多个
n
键,而且可能有我们不感兴趣的键,但它们具有相同的
散列槽
。我们实际上可以编写一个
Lua
脚本来在服务器中执行这些步骤
hash_name
- field_1: "2021-01-15;123"
- field_2: "2021-01-20;125"
- field_2: "2021-02-01;127"
val = redis.hget(hash_name, field_1)
timestamp = val.substring(0, val.index_of(";"))

if now() > timestamp:
  new_val = get_updated_value()
  new_timestamp = now() + EXPIRY_LENGTH
  redis.hset(hash_name, field_1, new_timestamp + ";" + new_val)
  val = new_val
else:
  val = val.substring(val.index_of(";"))

// proceed to use val