椭圆 您所在城市的活动中,未来的速度即将到来。

加入 Redis Released

有序集合时间序列

返回术语表

Redis 有序集合时间序列最佳实践

有序集合 (zset) 中的时间序列是 Redis 中对时间序列数据进行建模的典型方式。有序集合由具有评分的唯一成员组成,所有成员都存储在一个键下。对有序集合使用此数据类型意味着让评分作为某种时间指示(通常是毫秒精度的时间戳,但不总是),并且成员是记录的数据。唯一的需要注意的是,由于这是集合的一种形式,因此仅允许唯一成员,并且尝试记录与先前成员具有相同值的时间序列项只会更新评分。为了说明此问题,请看以下随着时间推移记录温度的示例

时间戳温度摄氏度
151153320500121
151153320600122
151153320700121

如果您仅使用ZADD将此内容直接作为有序集添加,您将错过一些数据点

反模式

> ZADD temperature 1511533205001 21
(integer) 1
> ZADD temperature 1511533206001 22
(integer) 1
> ZADD temperature 1511533207001 21
(integer) 0
>

ZRANGEBYSCORE

 temperature -inf +inf WITHSCORES
1) "22"
2) "1511533206001"
3) "21"
4) "1511533207001"

反模式

请注意第三个 ZADD 如何返回 0 – 这表示未将新成员添加到有序集中。然后,在 ZRANGEBYSCORE 中,我们可以看到该有序集仅有两个条目 (…7001 和 …6001),而缺少 …5001。为什么?在这种情况下,因为 …7001 和 …5001 都具有相同的成员 (21),所以我们仅更新了该成员的分数。这不好!

有多种方法可以解决此问题。首先是要包含一些具有足够熵的随机数据来确保唯一性。我们来检查一下此方法。首先,我们将在 0(包含)和 1(不包含)之间创建一个伪随机浮点数,然后将其添加到我们的时间戳。对于我们的示例,我们以十进制形式保留它以便于阅读(在实际工作负载中,为了节省存储空间,您最好只需将其转换回 8 个原始字节)。

> ZADD temperature2 1511533205001 21:1511533205001.2583
(integer) 1
> ZADD temperature2 1511533206001 22:1511533206001.941678
(integer) 1
> ZADD temperature2 1511533207001 21:1511533207001.732015
(integer) 1
> ZRANGEBYSCORE temperature2 -inf +inf WITHSCORES
1) "21:1511533205001.2583"
2) "1511533205001"
3) "22:1511533206001.941678"
4) "1511533206001"
5) "21:1511533207001.732015"
6) "1511533207001"

正如您所见,所有 ZADD 都会返回表示新添加内容的 1,而 ZRANGEBYSCORE 会返回所有值。这是一个可行的办法,但是它效率不高,会浪费字节来确保唯一性,从而增加了存储开销。对于大多数用例,唯一性将由您的应用程序直接放弃。需要注意的是,如果您的数据已经唯一(例如,一些包含 UUID 的数据),那么显然不需要添加唯一性。

使用此方法,您可以访问所有有序集方法,以便进行分析和操作

‡ ZINTERSTORE 和 ZUNIONSTORE 是多键操作。在分片环境中工作时,应小心确保新键最终位于同一分片上,否则这些命令将以错误结束。