Redis:以列表或排序集的形式呈现新闻提要



我正在用以下方式缓存Redis的扇形新闻提要:

每个feed活动都是一个键/值,如activity:id,其中值是数据的JSON字符串。

每个新闻提要当前都是一个列表,键是feed:user:user_id,列表包含相关活动的键。

检索新闻提要,我使用例如:'sort feed:user:user_id by nosort get * limit 0 40'

我正在考虑将提要更改为排序集,其中分数是活动的时间戳,这样提要总是按时间排序。

我读了http://arindam.quora.com/Redis-sorted-sets-and-lists-Pertaining-to-Newsfeed,它建议使用列表,因为排序集的时间复杂性,但通过继续使用列表,我必须照顾插入顺序,插入过去的故事需要遍历列表并找到要推送到的正确索引。(这会在分布式环境中导致新的问题)。

我应该继续使用列表还是使用排序集?

是否有一种方法可以从一个已排序的集合中立即检索新闻提要,(就像sort…获取*命令的列表),或者它必须是zrange,然后遍历结果并获得每个值?

是的,排序集非常快速和强大。它们似乎比SORT操作更符合您的要求。时间复杂性经常被误解。O(log(N))非常快,缩放也很好。我们用它来表示一个排序集中的数千万个成员。检索和插入时间低于毫秒。

使用ZRANGEBYSCORE key min max WITHSCORES [LIMIT offset count]得到你的结果。

根据你如何将时间戳存储为"分数",ZREVRANGEBYSCORE可能更好。

关于时间戳的一个小注释:不需要小数部分的排序集SCORES应该使用15位或更少的数字。所以SCORE必须保持在- 99999999999999999到99999999999999999的范围内。注意:这些限制的存在是因为Redis服务器实际上在内部将分数(float)存储为Redis字符串表示。

因此,我建议使用这种格式,将其转换为祖鲁时间:-20140313122802以获得秒精度。您可以为100ms的精度增加1位,但是如果不希望精度损失,则不能增加。顺便说一下,它仍然是一个float64,所以在某些情况下失去精度可能是好的,但你的情况适合"完美精度"范围,所以这就是我的建议。

如果您的数据在10年内过期,您也可以跳过前三位数字(CCYY的CCY),以达到0.0001秒的精度。

我建议负分数在这里,所以你可以使用更简单的ZRANGEBYSCORE代替REV一个。您可以使用 -inf 作为起始分数(负无穷)和LIMIT 0 100来获得前100名的结果。

两个排序集members (或'keys',但这是模棱两可的,因为排序集本身也是一个键)可以共享score,这没有问题,相同score中的结果是按字母顺序排列的。

希望有帮助,TW

聊天后编辑

OP想要从不同的键(GET/SETHGET/HSET键)收集数据(使用ZSET)。JOIN可以为你做这件事,ZRANGEBYSCORE不能。这样做的首选方法是使用一个简单的Lua脚本。Lua脚本在服务器上执行。在下面的示例中,为了简单起见,我使用EVAL,在生产环境中,您将使用SCRIPT EXISTSSCRIPT LOADEVALSHA。大多数客户端库都有一些内置的簿记逻辑,所以您不必每次都上传脚本。

example.lua:

local r={}
local zkey=KEYS[1]
local a=redis.call('zrangebyscore', zkey, KEYS[2], KEYS[3], 'withscores', 'limit', 0, KEYS[4])
for i=1,#a,2 do
  r[i]=a[i+1]
  r[i+1]=redis.call('get', a[i])
end
return r

您可以这样使用(原始示例,未为性能编码):

redis-cli -p 14322 set activity:1 act1JSON
redis-cli -p 14322 set activity:2 act2JSON
redis-cli -p 14322 zadd feed 1 activity:1
redis-cli -p 14322 zadd feed 2 activity:2 
redis-cli -p 14322 eval '$(cat example.lua)' 4 feed '-inf' '+inf' 100
结果:

1) "1"
2) "act1JSON"
3) "2"
4) "act2JSON"

最新更新