向大佬们请教一个关于排行榜的实现问题。
发布于 6 年前 作者 JZLeung 4150 次浏览 来自 问答

前提

有一堆帖子(大概 100w 条数据左右),有一个点赞的字段。

需求

实现本周和上周热门帖子排行榜,排序的根据是该帖子在本周或上周被点赞的数量来进行排行的。

同理,上月热门也是根据上月被点赞的数量来进行排行。

实现?

  • 新的统计表

    既然根据的是上周 /上月的数据来进行排序,那么可不可以新建一个表,专门记录每个帖子每周被点赞的数量?但是每月该怎么实现呢?而且这么做,好像数据量有点太大了。。。小肉鸡怕扛不住。

  • 缓存

    用 redis 去存?合理吗?

大佬们的见解?

不知道各位大佬们,有没有比较好的解决方法分享一下?

后端小白一枚,还请各位多多指教。

服务器环境

操作系统: ubuntu16.04 后台语言:nodejs v8.11.1 数据库:mongodb v2.6.10 服务器配置: 2c4g.

16 回复

Mongo的话每个帖子新建两个字段 stars_by_month stars_by_week 存储本月和本周的点赞量,每月初和每周初清零,排序的时候 order_by(stars_by_week)就行? total_stars, 90d_stars, 30d_stars, 7d_stars

理论上大多数历史帖子不会被翻出来点赞,所以估计10%的帖子会多出3个int字段,并且随着时间推移帖子数增多这个比例会下降,维持在特定数量(数量跟用户数和用户活跃度有关)。这三个字段还可以侧面反映社区活跃度。

没有实践经验,以上随便说的。

@loongmxbt 谢谢思路,有想过这种方法,但是上月和上周的怎么办?

@JZLeung 分为stars_this_month, stars_last_month,月末自动将stars_this_month的值给stars_last_month,然后stars_this_month在下月初清零。不知道这样可以么?

@loongmxbt 一百多万条数据,估计要跑很久吧,这配置。

什么情况的帖子的浏览量最大, 帖子分类了吗, 用户浏览一周热帖,不可能翻几百万条

redis, SortedSet结构,能排序+分页

来自酷炫的 CNodeMD

搞个持久化的redis服务 有序集合足矣

来自酷炫的 CNodeMD

用redis有序集合,集合数量设为固定100,只排前100名。 用4个有序集合来实现,本周,上周,本月,上月

  1. 当帖子赞数量变化时,更新前两个集合,
  2. 周初或月初时把前两个集合的数据复制到另外两个集合,然后清空。

优点:

相比于在mongodb中给每个帖子增加字段并排序来说更高效,每次直接从redis中取出列表就行

看在我打了那么多字,你也回答下我的问题吧:

https://cnodejs.org/topic/5b49c13c35342ab069061523

来自酷炫的 CNodeMD

@lovegnep 缺点是断电没,除非持久化。

但是如何知道该帖子的数量需要入库呢?

@zswnew

什么情况的帖子的浏览量最大,

未知。不固定的。

帖子分类了吗

有分类,但是排行榜不分类。

用户浏览一周热帖,不可能翻几百万条

确实不可能翻百万条,但是上万是肯定有的。

@JZLeung

  1. redis本身就支持持久化
  2. 用户对帖子点赞 ------》 在mongodb中更新并查询帖子点赞数量findAndModify -----》在redis中将帖子ID做为member,点赞数量做为score存入周榜和月榜zadd month score member(如果member已经存在集合中则redis会自动更新对应的score)

redis.zadd redis.zrevrangebyscore redis.expire 完美解决

难道不是直接按周和月份分组就行吗?

@aojiaotage 大佬能说下大概流程吗?

redis.zadd(`monthly_rank:${YYYY_MM}`, score, member ) //更新月记录YYYY_MM为某年某月
redis.zadd(`monthly_rank:${YYYY_MM_WW}`, score, member ) //更新周记录,YYYY_MM_WW为某年某月某周,可以用 moment 处理
redis.zrevrangebyscore(`monthly_rank:${YYYY_MM_WW}`, 0, 100) //取当周记录

到周/月切换的时候就自动换排行的key了,所以相当于到期清零

@aojiaotage score 一定要 int 型吗?

redis吧 不用担心断电,redis本身就支持持久化

回到顶部