7

我正在尝试存储媒体对象并通过redis在一定的时间范围内检索它们。我选择了一个排序集数据类型来执行此操作。我正在添加如下元素:

zAdd: key: media:552672 score: 1355264694
zAdd: key: media:552672 score: 1355248565
zAdd: key: media:552672 score: 1355209157
zAdd: key: media:552672 score: 1355208992
zAdd: key: media:552672 score: 1355208888
zAdd: key: media:552672 score: 1355208815

其中 key 对获取媒体的位置 id 是唯一的,并且 score 是媒体对象的创建时间。该值是媒体对象的 json_decode。

当我使用 检索时zRevRangeByScore,偶尔会有重复的条目。我本质上是使用 Redis 作为外部 API 的缓冲区,如果用户在 X 秒内进行两次相同的 API 调用,那么我将从缓存中检索结果,否则,我会将其添加到缓存中,而不是检查查看它是否由于定义了不包含重复项的集合而已经存在。可能的已知问题:如果媒体对象属性在缓存之间发生变化,它将显示为重复

有没有更好的方法来存储这种类型的数据而无需在 redis 客户端进行检查?

TLDR; 在 Redis 中存储和检索对象的最佳方式是什么,您可以通过时间戳选择一系列对象并确保它们是唯一的?

4

1 回答 1

25

让我们确保我们谈论的是相同的事情,所以这里是 Redis 排序集的术语:

ZADD key score member [score] [member]
summary: Add one or more members to a sorted set, or update its score if it already exists
  • key- 排序集的“名称”
  • score- 分数(在我们的例子中是时间戳)
  • member- 与分数相关的字符串
  • 一个有序集合有很多成员,每个成员都有一个分数

听起来您正在使用对象的 JSON 编码字符串作为成员。成员是排序集中的唯一成员。正如您所说,如果对象发生更改,它将作为新成员添加到排序集中。那可能不是你想要的。

排序集是 Redis 按时间戳存储数据的方式,但存储在集合中的成员通常是指向 Redis 中另一个键的“指针”。

根据您的描述,我认为您需要这种数据结构:

  • 按创建的时间戳存储所有媒体的排序集
  • 每个唯一媒体的字符串或哈希

我建议将媒体对象存储在散列中,因为这样可以提供更大的灵活性。例子:

# add some members to our sorted set
redis 127.0.0.1:6379> ZADD media 1000 media:1 1003 media:2 1001 media:3
(integer) 3
# create hashes for our members
redis 127.0.0.1:6379> HMSET media:1 id 1 name "media one" content "content string for one"
OK
redis 127.0.0.1:6379> HMSET media:2 id 2 name "media two" content "content string for two"
OK
redis 127.0.0.1:6379> HMSET media:3 id 3 name "media three" content "content string for three"
OK

有两种方法可以检索以这种方式存储的数据。如果您需要获取特定时间戳范围内的成员(例如:过去 7 天),则必须使用它ZREVRANGEBYSCORE来检索成员,然后遍历这些成员以获取每个哈希值HGETALL或类似值。请参阅流水线以了解如何通过一次调用服务器来执行循环。

redis 127.0.0.1:6379> ZREVRANGEBYSCORE media +inf -inf
1) "media:2"
2) "media:3"
3) "media:1"
redis 127.0.0.1:6379> HGETALL media:2
1) "id"
2) "2"
3) "name"
4) "media two"
5) "content"
6) "content string for two"

如果您只想获取最后 n 个成员(或例如:第 10 个最近到第 100 个最近的成员),您可以使用SORT来获取项目。请参阅排序文档以了解语法以及如何检索不同的哈希字段、限制结果和其他选项。

redis 127.0.0.1:6379> SORT media BY nosort GET # GET *->name GET *->content1) DESC
1) "media:2"
2) "media two"
3) "content string for two"
4) "media:3"
5) "media three"
6) "content string for three"
7) "media:1"
8) "media one"
9) "content string for one"

注意:按分数 ( ) 对已排序的哈希进行排序BY nosort仅适用于 Redis 2.6。

如果您计划获取最后一天、一周、一个月等的媒体。我建议为每个媒体使用单独的排序集,并用于ZREMRANGEBYSCORE删除旧成员。然后,您可以只使用SORT这些排序集来检索数据。

于 2012-12-13T16:06:08.720 回答