热门的规则
对于热门文章的定义是:
单位时间内,(”分享“数 + ”点赞“数 + ”评论“数)的总和大于某特定值的文章,被视为热门文章。
热门文章的列表是由后台动态生成的,而且在每次生成的时候,产生的数据不一定是相同的。为了减轻系统的压力和提高api的响应速度,该计算任务使用celery 进行后台任务调度。
后台定时任务是循环任务,任务执行时向缓存数据库中插入当前时段计算出的热门文章索引值,缓存数据库采用的是redis。
定时任务的实现
- 将新增的热门文章索引写入缓存数据库中,插入的时候,score 值取当前时间戳。
- 清除一定时间前的热门文章。
新增热门文章
计算热门文章sql 语句实现如下(暂时不考虑分享的数据):
1 | SELECT result.user_publish_id FROM ( |
(user_publish
用户发布文章信息表,user_like
用户点赞表,user_comments
用户评论表)
以上sql语句完成了对符合热门条件的文章的筛选,返回的结果集中将不包含应已经在缓存数据库的中索引。
将以上返回的文章索引插入redis:
1 | pipeline.zadd(ALL_HOT_KEYS_CACHE, time.time(), item) |
(ALL_HOT_KEYS_CACHE
redis 中有序集合的键)
写入完成之后,查看redis 中,其实每次任务产生的热门文章索引对应的score 值是相同的。
清除一定时间前的热门文章
热门文章进入缓存之后,需要在一定的时间内清除,这是因为被写入redis的之后,score不会被改动。定时任务需要将距离当前较远的缓存数据删除以减轻缓存的压力。
后端的实现
热门类别的分页没有上一页与下一页之说。客户端在请求的时候,有两种参数情况:
- count:要多少条数据
- ids:客户端已经缓存的文章id列表
客户端如果仅传入count 参数,后端将返回最新的count条数据信息。
如果传入count和ids,后端返回的count数据中,ids中包含的文章信息将不会被缓存。
这样保证了客户端数据的不重复问题。但是随着客户端浏览的数据越来越多,把么客户端请求的ids列表也越大,后端去重的时候复杂度较高。但是解决这个问题得力于redis的集合操作方法。
1 |
|
返回的数据排序按照redis返回的集合顺序。
客户端相关的任务
- 用户首次进入列表界面时,请求不要携带ids。
- 用户下拉刷新的操作同首次进入列表界面的操作。
- 用户上拉浏览列表的时候,需要携带ids,用于后端管理去重。
存在的问题
- 客户端访问时需要携带大量的已经缓存的文章id。
- 后端获取数据时的去重,随着ids越来越繁琐。
- 客户端处理较为繁琐
社区排行榜和热门列表的实现思路对比
相同:
- 顺序都是动态变化的
- 都需要额外的资源来保证需求的实现
- 客户端处理比较繁琐
不同:
- 社区排行榜是有序的,热门列表是设置门槛的。
- 社区排行榜是需要记录关注人数的。
- 社区有分页参数,热门列表是没有上一页下一页的概念的,仅需要声明count的大小。