2012-12-12 48 views
6

我正在嘗試存儲媒體對象,並讓它們通過redis在特定時間範圍內進行檢索。我已經選擇了一個有序集合數據類型來完成這個工作。我正在添加以下元素:確保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 

其中鍵的唯一位置是媒體拍攝的位置,分數是媒體對象的創建時間。值是媒體對象的json_decode。

當我去檢索使用zRevRangeByScore,偶爾會有重複的條目。我主要使用Redis作爲外部API的緩衝區,如果用戶使用X秒兩次進行相同的API調用,那麼我將從緩存中檢索結果,否則,我將它添加到緩存中,而不檢查以確定它是否已經存在,因爲不包含重複的集合的定義。 可能的已知問題: 如果媒體對象的屬性緩存之間的變化,它會顯示爲一個重複

有沒有更好的方式來存儲這種類型的數據不會對Redis的客戶端做檢查?

TLDR; 什麼是在Redis中存儲和檢索對象的最佳方式,您可以通過時間戳選擇一系列對象並確保它們是唯一的?

回答

23

讓我們確保我們在談論同樣的事情,所以這裏的術語對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來檢索數據。

+0

謝謝你,我正在尋找一個確切的事情。一個簡單的問題:我有一種情況,我不想重複,所以我在我的排序集中檢查它們,然後添加它們並創建哈希。我只是想問問這是否是一種矯枉過正? –