如何将服务器端时间戳作为分数存储在Redis排序集中?

如何将服务器端时间戳作为分数存储在Redis排序集中?,redis,Redis,我想使用一个排序集来存储使用redis服务器时间戳作为分数的对象 我知道我可以使用ReISIS流使用 */Cord>ID,但是ReDIS流有限制,包括我不能编辑对象,我不能使用秩或字典排序,我不能真正删除中间的对象,联合或交叉,等等。 我想以原子方式完成这项工作,并使用redis服务器时间戳,这样我就可以使用多个客户端来ZADD,而不用担心时钟同步 如何执行此操作?解决方案是使用Lua脚本: local time = redis.call('TIME') local ts = time[1]..

我想使用一个排序集来存储使用redis服务器时间戳作为分数的对象

我知道我可以使用ReISIS流使用<代码> */Cord>ID,但是ReDIS流有限制,包括我不能编辑对象,我不能使用秩或字典排序,我不能真正删除中间的对象,联合或交叉,等等。 我想以原子方式完成这项工作,并使用redis服务器时间戳,这样我就可以使用多个客户端来

ZADD
,而不用担心时钟同步


如何执行此操作?

解决方案是使用Lua脚本:

local time = redis.call('TIME')
local ts = time[1]..string.format('%06d', time[2])
return redis.call('ZADD', KEYS[1], ts, ARGV[1])
这里我们使用Redis。该命令返回:

  • unix时间(秒)
  • 微秒
所以我们可以把这两个连接起来,使用微秒的时间戳。我们需要将微秒部分归零

由于排序集适用于最大为2^53的整数值,因此我们的时间戳一直安全到2255年

这是Redis群集安全的,因为我们将其存储在一个密钥中。要使用多个键,请确保将它们放置在同一节点上,如果要比较时间戳,请使用

您可以修改脚本以使用低于微秒的分辨率

这里使用
EVAL
命令,简单地传递键和值作为参数,无需事先创建排序集:

EVAL "local time = redis.call('TIME') local ts = time[1]..string.format('%06d', time[2]) return redis.call('ZADD', KEYS[1], ts, ARGV[1])" 1 ssetKey myVal
和往常一样,您可能希望使用

关于Redis版本的说明。如果您正在使用:

  • Redis 3.2之前的版本:抱歉,您不能使用
    TIME
    (非确定性命令)然后使用
    ZADD
    进行写入
  • Redis版本大于3.2但小于5.0:在脚本顶部添加
    Redis.replicate_commands()
    。看
  • Redis 5.0升级版:你很好
> SCRIPT LOAD "local time = redis.call('TIME') local ts = time[1]..string.format('%06d', time[2]) return redis.call('ZADD', KEYS[1], ts, ARGV[1])"
"81e366e422d0b09c9b395b5dfe03c03c3b7b3bf7"
> EVALSHA 81e366e422d0b09c9b395b5dfe03c03c3b7b3bf7 1 ssetKey myNewVal
(integer) 1