我正在尝试存储媒体对象,并通过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
其中,密钥对于媒体被占用的位置ID是唯一的,并且分数是媒体对象的创建时间。值是媒体对象的json_decode。
当我使用zRevRangeByScore
进行检索时,偶尔会有重复的条目。我基本上使用Redis作为外部API的缓冲区,如果用户使用X秒进行两次相同的API调用,那么我将从缓存中检索结果,否则,我将其添加到缓存中,而不是检查由于定义不包含重复项的集合,查看它是否已存在。
可能的已知问题:
如果媒体对象属性在缓存之间发生更改,则它将显示为重复
有没有更好的方法来存储这种类型的数据,而无需在redis客户端进行检查?
TLDR; 在Redis中存储和检索对象的最佳方法是什么,您可以通过时间戳选择一系列对象并确保它们是唯一的?
答案 0 :(得分:24)
让我们确保我们谈论相同的事情,所以这里是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
或类似的每个哈希。请参阅pipelining,了解如何通过一次调用服务器来完成循环。
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
来获取项目。请参阅sort documentation了解语法以及如何检索不同的哈希字段,限制结果和其他选项。
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"
NB:按分数(BY nosort
)对已排序的哈希值进行排序仅适用于Redis 2.6。
如果您打算获取最后一天,一周,一个月等的媒体,我建议您为每个媒体使用单独的排序集,并使用ZREMRANGEBYSCORE
删除旧成员。然后,您可以在这些有序集上使用SORT
来检索数据。