当前位置: 首页 > 面试题库 >

Redis:扇出列表或排序集中的新闻提要吗?

孙朝明
2023-03-14
问题内容

我通过以下方式使用Redis缓存扇出新闻提要:

每个供稿活动都是键/值,例如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 … get *用于列表的命令),还是必须先进行zrange然后遍历结果并获取每个值?


问题答案:

是的,排序集非常快速且强大。与SORT操作相比,它们似乎更符合您的要求。时间的复杂性常常被误解。O(log(N))非常快,并且可以缩放。我们将其用于一组排序的数千万成员。检索和插入时间不到一毫秒。

使用ZRANGEBYSCORE key min max WITHSCORES [LIMIT offset count]让您的结果。

根据将时间戳存储为“分数”的方式,ZREVRANGEBYSCORE可能更好。

关于时间戳的简短说明:SCORES不需要小数部分的排序集应使用15位或更少的数字。因此,SCORE必须将其保持在-999999999999999到999999999999999的范围内。注:存在这些限制是因为Redis服务器实际上将分数(浮点数)存储为内部的Redis字符串表示形式。

因此,我建议将此格式转换为Zulu
Time
:-20140313122802以获取第二精度。您可以为100ms精度添加1位数字,但是
如果
您不希望损失精度,则可以再增加一位。顺便说一句,它仍然是float64,因此在某些情况下精度损失可能会很好,但是您的情况适合在“完美精度”范围内,因此,我建议这样做。

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

我在这里建议负分,这样你就可以使用更简单的ZRANGEBYSCORE,而不是REV一个。您可以将其 -inf
用作开始得分(减去无穷大)并LIMIT 0 100获得前100名的结果。

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

希望这会有所帮助,TW

聊天后编辑

OP想要ZSET从不同的键(GET/ SETHGET/
HSET键)收集数据(使用)。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"


 类似资料:
  • 问题内容: 是否有人在Redis中实现了任何形式的有上限的数据结构?我正在构建类似新闻提要的东西。提要将非常频繁地被操纵和读取,并且将其保存在Redis的分类集中对于我的用例来说是便宜又完美的。唯一的问题是,每个提要仅需要n个项,并且我担心内存溢出,因此我想确保每个提要都不会超过n个项。用Lua在Redis中创建一个有上限的排序集合似乎很简单: update_feed.lua看起来像(未经测试):

  • 问题内容: 我目前正在使用“设置”结构使用Redis。 我想知道是否有可能自动清理空的“ set”吗? 否则找到一个cron /进程来定期清理空的“ set” 更新: 更笼统的问题是,“(nil)”和“(空列表或集合)”之间存在差异(内存使用情况) 例: 要么 问题答案: 这已经是自动的。如果集合为空,则将其从名称空间中删除。 您不必执行任何特定操作即可从此行为中受益。 要回答第二个问题,(nil

  • 问题内容: 我有许多排序后的集合用作系统上的二级索引,用户查询可能会碰到其中的一些。 要使用这些索引来使所有30岁以下且得分> 2的用户 但这意味着我已将所有数据从redis复制到我的应用服务器以执行交叉,是否有更有效的方法来执行此操作,而不是通过网络传输所有匹配范围,而是在Rediss中进行交叉? 我想要的是 ZRANGEBYSCORESTORE在其中执行ZRANGEBYSCORE操作并将结果存

  • 问题内容: 在Redis排序集中获得SCORES总数的最佳方法是什么? 问题答案: 我认为唯一的选择是迭代排序后的集合并计算总和客户端。

  • 问题内容: 我想具有重新排列表中的行的功能(使用拖放对行进行排序)。 并且行排列的索引在模型中也应更改。 如何 使用Angular Directive 做类似的事情:http : //jsfiddle.net/tzYbU/1162/? 我正在生成表为: 问题答案: 我做的。请参阅下面的代码。 的HTML 指令(JS)

  • 我正在做一个项目,所以我把我的问题简化为: 任何帮助都将不胜感激。