
关于实时TopN排名算法的思考
发布日期:2021-05-06 08:36:39
浏览次数:12
分类:技术文章
本文共 1518 字,大约阅读时间需要 5 分钟。
关于实时TopN排名算法的思考
0.引言
实时排名是网络应用中常见的功能。根据需求不同,大概可以分为以下几类:
- i. TopN排名
- ii. 全数据排名
作为通用需求,我们必须做如下假设:
- a. 用户基数较大
- b. 排名数据更新较频繁
- c. 用于排序的数据(score)范围不确定
- d. 用作排名的score只会增加,不会减少
基于以上假设,全数据排名就是海量数据处理问题,一般认为内存难以胜任,一般通过数据库(如redis)实现,本文暂不讨论。
1.TopN实时排名算法
这里,我们假设:
- N的范围有限(如1000),榜单数据内存完全可以处理
那么,问题来了。如何设计数据结构和算法,来满足大批量用户频繁更新榜单情况下的实时排名需求?
1.1 一个失败的方案
曾经看到一个实现,方案如下:
- a. 定义一个长度为N+1的数组
- b. 更新数据时,将新数据放到数组尾部
- c. 对数组排序,如果数组长度为N+1,则移除尾部元素
咋一看,由于榜单数据较小,每次更新排序好像可行,但是随着用户基数和更新频度增加,
这个算法无疑跟DB设计把query建立在没有index的table上一样可怕。随着更新频度提升,这个sort操作无疑将成为CPU的噩梦。
低效率的算法不会出bug,但是隐藏在角落偷偷的吃CPU,还很难被发现。
因此,该方案不可取。
1.2 现成的数据结构?
经典的有序数据结构,如
- 红黑树
- Heap
貌似可以满足这种需求。
但是,我们知道,平衡二叉树的高效操作是在于快速查找,然而维护一棵树的平衡(插入,删除元素),却是成本很高的操作。
因此,不可取。
1.3 合理的方案
这个功能里有一个令人头疼的要求,就是客户端要实时能够查看到排名情况,那么问题来了:
- 这里的实时是否意味着服务端数据必须实时有序?
答案是未必。我们知道,排序算法是计算机里面一个比较耗时的操作,频繁的排序更是无法忍受。
比较可行的方案是服务端不排序,只保证榜单记录TopN的数据,把实时排序的任务交给客户端执行。
- 服务器如何保证榜单上只记录TopN的数据?
数据结构定义如下:
type RankInfo struct{ name string // name of this rank element score int // rank score}type RankList struct { list []*RankInfo // unordered top N rank list min *RankInfo // the last one who own the minimum score in list nameMap map[string]*RankInfo // name->rankInfo}
更新积分榜UdateRankList(name, score)的操作流程如下(假设score只会增加不会减少):
- a. 从nameMap查找指定的name是否已在榜单上,如果存在,更新积分。如果该对象==min,则重新查找积分最低对象赋值给min,返回。
- b. 如果list长度<N, 则直接将新数据插入list尾部,如果score<min.score,则将新对象赋值给min, 返回。
- c. 如果score>min.score, 则顶替min对象数据,,min.score为name,score,重新查找积分最低对象赋值给min, 返回。
- d. 所给score不能上榜。
至此,排行榜更新完成。不需要排序,不需要支持排序的数据结构,高效的完成榜单维护,perfect。
Reference
发表评论
最新留言
能坚持,总会有不一样的收获!
[***.219.124.196]2025年03月08日 20时43分43秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
干货丨RPA售前六技能
2019-03-01
MVC之修改
2019-03-01
使用pycharm链接数据库MySQL
2019-03-01
Linux基础学习笔记
2019-03-01
struct 模块
2019-03-01
析构方法 __del__
2019-03-01
python之面向对象编程
2019-03-01
Docker Compose 搭建 Redis Cluster 集群环境
2019-03-01
python之集合类型内置方法
2019-03-01
编程与编程语言分类
2019-03-01
python之三元表达式、生成式、生成器表达式
2019-03-01
python之pickle模块
2019-03-01
【高速接口-RapidIO】5、Xilinx RapidIO核例子工程源码分析
2019-03-01
视觉SLAML1作业
2019-03-01
【一只蒟蒻的刷题历程】 【HDU-1276】 士兵队列训练问题
2019-03-01
【 UVA - 572 】 Oil Deposits (DFS水题)
2019-03-01
【Linux】 Linux实操 --- 开机、重启和用户登录注销
2019-03-01
RBF神经网络——案例一
2019-03-01