如何以服务器端时间戳作为分数存储在Redis排序集中? [英] How to store in Redis sorted set with server-side timestamp as score?

查看:66
本文介绍了如何以服务器端时间戳作为分数存储在Redis排序集中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用一个排序的集合来存储使用 redis-server 时间戳作为分数的对象.

I want to use a sorted set to store objects using the redis-server timestamp as score.

我知道我可以使用带有 * id 的 Redis Streams,但是 Redis Streams 有一些限制,包括我不能编辑对象,我不能使用排名或字典排序,我不能真正删除中间的对象、联合或相交等

I know I can use Redis Streams with * id, but Redis Streams have limitations, including I cannot edit the objects, I cannot use rank or lexicographical sorting, I cannot really delete objects in the middle, unions or intersects, etc.

我想以原子方式执行此操作,并使用 redis-server 时间戳,以便我可以使用多个客户端来ZADD 而不必担心时钟同步.

I want to do this atomically, and use the redis-server timestamp so I can use multiple clients to ZADD without worrying about clock-sync.

如何做到这一点?

推荐答案

解决方案是使用 Lua 脚本:

The solution is to use a Lua script:

local time = redis.call('TIME')
local ts = time[1]..string.format('%06d', time[2])
return redis.call('ZADD', KEYS[1], ts, ARGV[1])

这里我们使用 Redis TIME 命令.命令返回:

Here we use Redis TIME command. The command returns:

  • unix 时间(以秒为单位)
  • 微秒

所以我们可以连接这两个并使用微秒时间戳.我们需要对微秒部分进行零填充.

So we can concatenate these two and use a microsecond-timestamp. We need to zero-pad the microseconds part.

由于排序集适用于高达 2^53 的整数值,因此我们的时间戳一直到 2255 年都是安全的.

Since sorted sets are good with integer values up to 2^53, our timestamp is safe all the way up to the year 2255.

这是 Redis 集群安全的,因为我们存储在一个键中.要使用多个键,请确保使用 hash 标签 如果你想比较时间戳.

This is Redis-Cluster-safe as we store in one key. To use multiple keys, make sure to land them on the same node using hash tags if you want to compare timestamps.

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

You can modify the script to use lower than microsecond resolution.

这里是EVAL命令,简单的pass key和value作为参数,不需要事先创建sorted set:

Here the EVAL command, simple pass key and value as arguments, no need to create the sorted set before hand:

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

与往常一样,您可能希望加载脚本并使用EVALSHA.

As always, you may want to load the script and use EVALSHA.

> 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

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

A note on Redis version. If you are using:

  • Redis 3.2 之前的版本:抱歉,您不能使用 TIME(非确定性命令)然后使用 ZADD 编写.
  • Redis 版本大于 3.2 但
  • 5.0:在脚本顶部添加 redis.replicate_commands().请参阅脚本作为纯函数
  • Redis 5.0 升级版:你很好.
  • Redis Version before 3.2: sorry, you cannot use TIME (non-deterministic command) and then write with ZADD.
  • Redis Version greater than 3.2 but < 5.0: Add redis.replicate_commands() on top of the script. See Scripts as pure functions
  • Redis 5.0 an up: you are good.

这篇关于如何以服务器端时间戳作为分数存储在Redis排序集中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆