带老弟做个实时排行榜

阿巴可懂的实时排行榜设计和实现思路。

大家好,我是鱼皮,暑假快到了,我的老弟小阿巴听说我家有很多好康的,就跑来找我玩。

结果我摆出了几个以前开发过的小系统,准备在这段时间带着小阿巴多做些作品,学习编程项目的设计思路。这样等他开学了,就可以更轻松地跟着老师做做项目了。

今天,就先带他做一个很常见的小功能:用户实时积分排行榜。

实时积分排行榜

需求

先描述下需求,在我的编程导航项目中,为了鼓励大家共同维护网站,用户可以通过推荐资源、积极评论、举报违规资源等方式获取积分。

为了进一步激励大家,网站需要提供一个用户积分排行榜,分为 实时总积分榜周榜月榜,均 只取前 10 名 。所有用户都能够查看当前排行榜,以及查看自己的 实时 总积分排名,后续管理员就可以给上榜用户颁发奖品了。

效果如下图:

点击 我的排名 按钮,可以查看自己的实时排名:

本文篇幅有限,先仅讨论 实时总积分榜 的设计实现。

听了需求后,小阿巴爽朗一笑:这有啥难的?且让我设计一波,再给你娓娓道来。

设计实现

先看下数据库的结构,总共有 2 个表:用户表用户积分表

用户表存储了用户信息,以及用户的总积分(实时更新),也就是说总积分榜需要的数据可以直接从这里取到,不需要再去计算。

用户表内容:

用户 id用户名积分(score)
1小阿巴10
2李鱼皮1000
3小李100
......

100李老热66

如果要取前 10 名,只需要把所有用户的信息先取出来,再排个序就好啦,写 SQL 语句查询的话就是:

select * from `user` order by score;

然后如果要取自己的总排名,就对查到的有序数据进行一次遍历,找到自己所在的位置下标就行,伪代码如下:

// 从数据库查询全部用户列表
list = getAllDataList()
for(i = 0; i < total; i++) {// 找到自己的位置if(list[i].id == '我的id') {return i + 1;}
}

小阿巴得意到:这不就实现总积分榜了么?你这需求太简单,啧啧。

我笑到:还不错,总积分榜的思路是正确的,起码知道要对所有的数据进行排序。但如果用户数特别多呢?比如几十万个,你只需要查自己的总排名,还需要把全部的数据都做一个排序么?

小阿巴陷入沉思,想了半天,没想出来。

于是我提示到:假如在一次考试中你想知道自己的排名,是不是只需要知道有多少人的分数比自己高就行了,不用去管其他人排第几对吧?

小阿巴一拍脑袋:对啊,我只需要先查出自己的分数,然后统计分数大于我的用户数量,不就知道自己的排名了?

先用 SQL 语句查出用户的分数:

/* 只取需要的列 */
select score as myScore
from `user`
where id = "用户 id";

然后再用 SQL 语句统计分数大于该用户分数的数量:

select count(*) from `user`
where score > myScore;

最后只需要将该查询结果加 1,就是自己的排名啦~

小阿巴感叹到:原来转换一点点思路,就能省去多余的排序带来的性能开销,起飞~

更多思考

鱼皮:先别起飞,其实对于一般用户量的系统,上面的方案就已经足够了。下面让我们加大难度,假如用户数再多一点点呢,比如说一亿个,怎么实时获取前 10 名呢?

小阿巴:还真是 “亿点点”,就您那破编程导航还想着有一亿个用户?

鱼皮:少废话,梦想还是要有的,万一有亿个用户呢?快想想系统怎么做!

小阿巴:且不说对一亿个数据排序有多慢,能不能存的下都是个问题啊。。。啊,等等,这难道就是面试常见的 Top N 问题!

鱼皮:不错,我面试的时候被问过好几次 Top N 问题,如何从海量数据中找出前 N 个数呢?

小阿巴:这我完全不懂啊,算法不会,真要命。

鱼皮:其实 Top N 问题的核心在于保证空间和时间复杂度,先要考虑数据能存入内存运算,在怎样算得更快。

通常 Top N 问题有下列几种解决方案。

Top N 解决方案

全部排序

直接对所有数据进行排序(快排等),缺点是需要将数据一次性加载到内存中。

局部淘汰

内存中维护一个大小为 N 的容器,再让剩余的数一个个进入容器,并淘汰容器内的最小值。最终容器内剩下的数就是前 N 名。优点是能节省内存,缺点是太慢了。

分治

把数据分为多个小组,小组内先分别选出前 N 名小组长,最后再让这些小组长同台竞技,选出最终的前 N 名。

哈希预处理

假如数据重复度很高,可以通过 hash 的方式,去掉很多重复数据。比如 1 亿个数据里,一半是 0,一半是 1,那么取前 10 名时,可以直接淘汰掉另一半为 0 的数据。

但是预处理本身也需要时间和空间,这就需要我们对数据的重复度有一个清晰的判断,否则自作聪明、适得其反。

小根堆

面试算法中的高频考点 —— 堆排序,可以先取前 N 个数组成小根堆,堆顶始终是最小值。然后遍历后续数字,大于堆顶就替换掉堆顶并调整最小堆结构。该算法时间复杂度和空间复杂度(为 N,常数)都不错,所以必须要掌握。

但是具体选择哪种方案呢?还是要结合我们实际的项目和业务场景来分析。

实际解决

由于我们的数据库来记录积分,所以当用户量级很大时,首先要 分库分表 ,通常是水平分表,根据一定规则(比如 id)把用户数据行分批存储在多个数据表中。

分表

然后就和大数据 Map / Reduce 处理机制一样了,可以采用 分治 的方式 并行计算 每个表的前 10 名(map),都计算好后,再汇总到一起计算最终的前 10 名(reduce)。

一次大数据并行处理过程

用这种方式,别说 1 亿了,2 亿、3 亿的计算模式都是一样的,加机器水平扩容就好了~

所以遇到 Top N 问题的时候,大家可以先答一下上面的几种方案,再结合具体的场景分析,分治和最小堆是我觉得相对 核心 的点。

Redis

最后,对于实时排行榜的设计,肯定很多背过八股文面试题的朋友在第一时间会想到使用 Redis 的有序集合 zset,的确也是一种方案,但也要结合场景去分析利弊,不要秒答。

使用基于内存的 Redis zset 的确运算更快,且天然支持排序、使用方便。但数据量大时同样面临数据更新、维护、同步、持久化存储等问题,而且对于我们这种实时性要求不高的需求来说,有些大材小用了哈哈。

zset 数据结构




我是鱼皮,周末肝文不易,如果觉得文章不错,希望 点赞 + 在看 支持下,给俺点创作动力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/301313.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

每日一笑 | 在托运行李时,怎样才能不会因为超重被罚钱?

全世界只有3.14 % 的人关注了数据与算法之美&#xff08;图片来源于网络&#xff0c;侵权删&#xff09;

加时间水印_如何在手机照片上添加时间和日期?打开这个设置即可添加,超方便...

经常在朋友圈或者微博刷到一些照片&#xff0c;上面带有拍照时间和地点&#xff0c;甚至是天气&#xff0c;很多人还不知道是怎么操作的吗&#xff0c;今天小编就来告诉大家怎么操作&#xff0c;1分钟包学包会&#xff01;1、照片添加文字、地址、天气打开手机相机&#xff0c;…

少儿编程教育是“揠苗助长”还是要培养未来的程序员?

▲数据汪特别推荐点击上图进入玩酷屋去年有一款名叫CoderMindz的棋类游戏在硅谷名声大噪&#xff0c;它的前身CoderBunnyz发布不到一年时间&#xff0c;销量超过1000余套&#xff0c;销售额以超35000美元&#xff0c;因此大家对新款CoderMindz充满期待。而这款游戏的开发者&…

日志ILog(文件日志/控制台日志/控件日志/网络日志)

日志组件是NewLife系列组件最早最基础&#xff0c;同时也是流血流泪最多的一个模块&#xff0c;它的底蕴定能感动每一个用户&#xff01;没有日志的应用系统是不完整的。系统遇到啥问题&#xff0c;翻日志看看当时上下文&#xff0c;实在分析不出问题&#xff0c;修改代码再打几…

php crypt mysql password_php使用crypt()函数进行加密

一、代码$str 应用crypt()函数进行单向加密!; //声明字符串变量$strecho 加密前$str的值为&#xff1a;.$str;$crypttostr crypt($str); //对变量$str加密echo 加密后$str的值为&#xff1a;.$crypttostr; //输出加密后的变量?>二、运行结果参数不带salt&#xff0c;每次…

.NET 容器环境下创建应用 dump 文件

.NET 容器环境下创建应用 dump 文件Intro有时候我们的应用会出现一些异常的情况&#xff0c;比如内存飙升&#xff0c;线程死锁等等&#xff0c;通过一些 metrics 我们可能大概的了解内存是增长了&#xff0c;但是具体是哪里增长了&#xff0c;单单看内存的变化很难看出来哪里导…

安装mysql二进制文件_MySQL二进制文件规范安装

演示环境介绍操作系统&#xff1a;CentOS 6.7 (64位)二进制包&#xff1a;MySQL-5.6.30-linux-glibc2.5-x86_64.tar.gzMySQL 下载地址&#xff1a;http://dev.mysql.com/downloads/1、下载MySQL# mkdir /root/mysql# cd /root/mysql# wget http://dev.mysql.com/get/Downloads…

清华体质优良可降5分录取;窃取密钥者奖百万;阿里投入1亿保护方言;腾讯不正当竞争被罚;这就是今天的大新闻...

今天是3月21日农历二月十五今天星期四网络突然变得特别的卡严重影响到我的激情下面是今天的大新闻清华体质优良可再降5分录取&#xff08;中国新闻网&#xff09;据清华大学招生办公室官方微信消息&#xff0c;2019年清华大学将继续在自主招生中开展体质测试。体质测试成绩优良…

[Android]关于IntentService

2019独角兽企业重金招聘Python工程师标准>>> IntentService其实是Service加Handler的组合&#xff0c;Handler存在于专门的HandlerThread上&#xff0c; 区别于UI thread, Service每通过onStart()收到Intent&#xff0c;则转给Handler,通过handleMessage()的方式一个…

Facebook 竟然把服务 27 亿人的 AI 硬件系统开源了?!

全世界只有3.14 % 的人关注了数据与算法之美一直以来&#xff0c;社区对 Facebook 的硬件研究比较关注。在今日的开放计算项目全球峰会上&#xff0c;Facebook 技术策略主管 Vijay Rao 开源了全新的 AI 硬件&#xff1a;面向 AI 训练与推理的硬件系统 Zion 与 Kings Canyon&…

一秒创建高级查询服务

在业务开发中&#xff0c;一个常用的功能就是“高级查询”&#xff0c;就是客户可以根据自己的需要设置查询条件查找数据&#xff0c;类似下图&#xff1a; 通常&#xff0c;我们需要为每个“高级查询”定制Dto类&#xff0c;用于传输条件&#xff0c;并要根据条件组合成查询语…

首款产后抑郁药问世;京东推出城市操作系统;阿里将推出全新销售平台;香港政府砸5300亿填海;脸书再爆隐私丑闻;这就是今天的大新闻...

今天是3月22日农历二月十六今天星期五一周就这么过去了周末得好好耍下面是今天的大新闻首款产后抑郁药问世&#xff08;红星新闻&#xff09;据美国CNN新闻3月19日报道&#xff0c;当地时间本周二&#xff08;19日&#xff09;&#xff0c;美国食品和药物管理局&#xff08;FDA…

navicat如何连接腾讯mysql_使用Navicat连接腾讯云Mysql数据库

1、安装# 安装mysql服务sudo apt-get install mysql-server# 安装客户端sudo apt install mysql-client# 安装依赖sudo apt install libmysqlclient-dev# 检查状态sudo netstat -tap | grep mysql2、设置密码root> mysqlmysql> update mysql.user set authentication_str…

WPF实现环(圆)形进度条

WPF开发者QQ群&#xff1a; 340500857 | 微信群 -> 进入公众号主页 加入组织“ 前言&#xff0c;接着上一篇圆形菜单。”欢迎转发、分享、点赞、在看&#xff0c;谢谢~。 01—效果预览效果预览&#xff08;更多效果请下载源码体验&#xff09;&#xff1a;02—代码如下一、…

JQuery上传插件Uploadify使用详解

Uploadify是JQuery的一个上传插件&#xff0c;实现的效果非常不错&#xff0c;带进度显示。不过官方提供的实例时php版本的&#xff0c;本文将详细介绍Uploadify在Aspnet中的使用&#xff0c;您也可以点击下面的链接进行演示或下载。官方下载官方文档官方演示首先按下面的步骤来…

每日一笑 | 不忘初心,最爱扫雷~

全世界只有3.14 % 的人关注了数据与算法之美&#xff08;图源网络&#xff0c;侵权删&#xff09;

在ASP.NET Core微服务架构下使用数据库切分和扩展

原文链接&#xff1a;https://itnext.io/how-to-use-database-sharding-and-scale-an-asp-net-core-microservice-architecture-22c24916590f微服务的一大优点是&#xff0c;它们可以独立扩展。本文展示了扩展一个微服务及其数据库的好处和挑战。您将创建一个示例应用程序并手动…

GridView实现数据编辑和删除(一)

2019独角兽企业重金招聘Python工程师标准>>> 前台的html代码&#xff1a; <asp:GridView ID"gv_Emplogin" runat"server" AutoGenerateColumns"False" onrowdeleting"gv_Emplogin_RowDeleting" onrowupdating"gv_…

8张图告诉你,在朋友圈发什么不会被嫌弃

爱发圈的你是否发现&#xff0c;打开朋友圈总有一些内容让你嫌弃&#xff1a;和本人真假难辨的美图自拍&#xff0c;每天十条以上的发帖&#xff0c;伪科普的转发…还有一些人你直接想删除&#xff1a;炫耀自己家的奢侈品&#xff0c;从不交摊位费的代购和微商和一日三餐都发圈…

iNeuOS工业互联网平台,在高校教学实训领域的应用

目 录1. 概述... 22. 实训柜... 23. 培训内容... 44. 二次开发培训... 51. 概述中国工业互联网从 0 向 1 演进从缺政策、缺技术、缺市场&#xff0c;逐渐转移到了缺人才&#xff0c;跨行业、跨领域的复合型人才&#xff1b;IT与OT融合型人才&#…