nie题目-游戏排行榜设计
一个mmorpg游戏,玩家众多,需要对玩家战斗力进行排行,并且战斗力变化时需要及时刷新。需要设计一个这样的排行榜。
关于海量数据排行榜的做法,云风在他的博客里给过思路,谈谈陌陌争霸在数据库方面踩过的坑(排行榜篇)。主要思路是利用桶排序思路,对于大量相同分数玩家的处理则直接划归为同一等级。即游戏排行榜主要是对前n名玩家进行插入排序,这里的n可以取几百或更多,这样大为减少了排序压力。
陌陌争霸怎样做排行榜的?
在上一篇里就有同学问道,如果你们不用数据库,怎么做排行榜呢? 其实我在上一篇正文里就有解答:
“服务器只是在不断的创造新数据并让这些数据在内存中流通而已,它没有任何需要从外部读取数据。如果内存无限大,且服务器永远不会当机,数据库这个设施没有存在的必要。”
排行榜单也是数据之一,游戏服务器开服一刻起,没有任何玩家有排名信息。随着玩家名次更替,榜单才逐步形成。我们只需要在玩家分数变化的时候同步榜单的变化即可。而玩家查询仅仅是取走有序的榜单而已。
你看,这个过程和数据库无关不是?需要设计的是调整榜单的算法,和榜单的数据结构以保证维持榜单的性能足够强就好了。因为玩家名词更替的频率远小于玩家网络包的频率,那么这个模块的处理能力所需要的下限很容易满足。我们不用考虑处理不过来的情况。
针对陌陌争霸我们是这样做的:
陌陌争霸中用于排名的分数区间不大,也就是 0 分到 5000 分。而参与排名的人数众多,数以百万计。对百万用户做插入排序,每个插入即使是 O(N) 的也不可接受。可事实是大量玩家的分数相同,都是并列排名的。所以我们只需要做 5000 个桶,每个桶里仅记录这个分数有多少个人就可以了。
当玩家分数变迁,把原来的桶减一,新的桶加一。这个操作就是 O(1) 的。
而排行榜的查询仅需要把当前分数靠前的桶累加,就能获知查询者的名次。对于上百万玩家,看到哪些人和你并列的人的名字是没有意义的。这个查询虽然是 O(n) 复杂度,但 n 只有区区 5000 ,还可以做 cache 以应对查询频率远高于更新频率的情况。
真正需要精确知道人名的是榜单的前 200 个人,而对前 200 个人做插入排序也很快,所以并不会造成性能问题。
我们在系统的单点做排行榜的维持,完全没有外部数据库操作,它只是一小段操作普通内存结构的 c 代码。而这个单点远远成为不了整个系统的热点。
我们在系统临时退出时,把已经排好的榜单落地,下次启动的时候恢复。但也不必完全信任落地的数据,可以用离线脚本检索整个数据库重新生成一份正确的榜单。所以数据库中的榜单只是被 cache 起来而已,系统运行期间是不需要写入数据库的,也不用担心数据丢失。
关于桶排序,贴一个wikepedia的简要算法介绍:
桶排序 (Bucket sort)或所谓的箱排序,是一个排序算法,工作的原理是将数组分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)。桶排序是鸽巢排序的一种归纳结果。当要被排序的数组内的数值是均匀分配的时候,桶排序使用线性时间(Θ(n))。但桶排序并不是 比较排序,他不受到 O(n log n) 下限的影响。
桶排序以下列程序进行:
- 设置一个定量的数组当作空桶子。
- 寻访序列,并且把项目一个一个放到对应的桶子去。
- 对每个不是空的桶子进行排序。
- 从不是空的桶子里把项目再放回原来的序列中。
伪代码如下:
思路比较简单,每个桶使用链表,插入至相应桶(链表)时保持有序,排序时归并链表。c++实现如下:
假设数据分布在[0,100)之间,每个桶内部用链表表示,在数据入桶的同时插入排序。 然后把各个桶中的数据合并。 #include<iterator>
#include<iostream>
#include<vector>
using namespace std;
const int BUCKET_NUM = 10; struct ListNode{
explicit ListNode(int i=0):mData(i),mNext(NULL){}
ListNode* mNext;
int mData;
}; ListNode* insert(ListNode* head,int val){
ListNode dummyNode;
ListNode *newNode = new ListNode(val);
ListNode *pre,*curr;
dummyNode.mNext = head;
pre = &dummyNode;
curr = head;
while(NULL!=curr && curr->mData<=val){
pre = curr;
curr = curr->mNext;
}
newNode->mNext = curr;
pre->mNext = newNode;
return dummyNode.mNext;
} ListNode* Merge(ListNode *head1,ListNode *head2){
ListNode dummyNode;
ListNode *dummy = &dummyNode;
while(NULL!=head1 && NULL!=head2){
if(head1->mData <= head2->mData){
dummy->mNext = head1;
head1 = head1->mNext;
}else{
dummy->mNext = head2;
head2 = head2->mNext;
}
dummy = dummy->mNext;
}
if(NULL!=head1) dummy->mNext = head1;
if(NULL!=head2) dummy->mNext = head2; return dummyNode.mNext;
} void BucketSort(int n,int arr[]){
vector<ListNode*> buckets(BUCKET_NUM,(ListNode*)(0));
for(int i=0;i<n;++i){
int index = arr[i]/BUCKET_NUM;
ListNode *head = buckets.at(index);
buckets.at(index) = insert(head,arr[i]);
}
ListNode *head = buckets.at(0);
for(int i=1;i<BUCKET_NUM;++i){
head = Merge(head,buckets.at(i));
}
for(int i=0;i<n;++i){
arr[i] = head->mData;
head = head->mNext;
}
}
nie题目-游戏排行榜设计的更多相关文章
- 基于redis的排行榜设计和实现
前言: 最近想实现一个网页闯关游戏的排行榜设计, 相对而言需求比较简单. 秉承前厂长的训导: “做一件事之前, 先看看别人是怎么做的”. 于是乎网上搜索并参考了不少排行榜的实现机制, 很多人都推荐了r ...
- 基于cocos2d-x的游戏框架设计——李成
视频:http://v.youku.com/v_show/id_XMzc5ODUyMTI4.html?f=17330006 网易科技讯 3月31日,第四届CocoaChina开发者大会暨Cocos2d ...
- 课程设计个人报告——基于ARM实验箱的捕鱼游戏的设计与实现
课程设计个人报告--基于ARM实验箱的捕鱼游戏的设计与实现 一.个人贡献 参与课设题目讨论及部分过程 资料收集 负责代码调试 捕鱼游戏相应功能的实现 实验环境 Eclipse软件开发环境: ARM实验 ...
- FPS游戏服务器设计的问题 【转】
一.追溯 去gameloft笔试,有一个题目是说: 叫你去设计一个FPS(第一人称射击游戏),你是要用TCP呢还是要用UDP,说明理由 . 二.学习 这是两篇网上找到的文章,写非常不错. 当时笔试的时 ...
- (转)FPS游戏服务器设计的问题
FPS游戏服务器设计的问题出处:http://www.byteedu.com/thread-20-1-1.html一.追溯 去gameloft笔试,有一个题目是说: 叫你去设计一个FPS(第一人称射击 ...
- 编程语言性能游戏排行榜,C/C++第一ATS第二JAVA第三
编程语言性能游戏排行榜,C/C++第一ATS第二JAVA第三 编程语言性能游戏排行榜,C/C++第一ATS第二JAVA第三
- Elixir游戏服设计五
在<Elixir游戏服设计一>里提到,按照系统功能划分成app要保证原子性很难, 现在想想也没那么难.保证原子性,无非就是需要某个单点去完成操作.那么选择玩家进程去做原子性工作就可以了. ...
- Elixir游戏服设计一
在Erlang游戏服设计总结http://www.cnblogs.com/rubyist/p/5530575.html里, 我提到我想要的游戏服设计方法,希望以应用做为基础构建块.最近我在学习elix ...
- Erlang游戏服设计总结
这主要是一年多来,个人从事Erlang游戏服开发中对一些事情的思考. 想到哪说到哪,没有条理可言. 欢迎讨论. 通常Erlang游戏服务的设计涉及到的东东包括如下: 任务系统 活动系统 公会系统 玩法 ...
随机推荐
- 使用「max-height」实现自适应高度
.tab-content{ max-height: 0; overflow: hidden; -webkit-transition: max-height .8s; -moz-transition: ...
- HDU 5858 Hard problem (数学推导)
Hard problem 题目链接: http://acm.split.hdu.edu.cn/showproblem.php?pid=5858 Description cjj is fun with ...
- global & nonlocal
name = "A" def test(): name = "B" def test2(): global name # global 指的是拿到的是全局的变量 ...
- oradmin相关用法
[转]oradmin相关用法 创建例程: -NEW -SID sid | -SRVC 服务 [-INTPWD 口令] [-MAXUSERS 数量] [-STARTMODE a|m] [-PFILE 文 ...
- 如果浏览器自动调用quirks模式打开的话
(从已经死了一次又一次终于挂掉的百度空间人工抢救出来的,发表日期 2014-03-21) 则肯定你的html的声明,没有写好. 今天遇到几个,前面莫名其妙的多了个空格(在网页上看源码是多空格,复制到n ...
- requests设置headers,proxies,cookies
header = {'referer':'http://www.baidu.com'} # referer代表从什么网页跳过来的,其他属性同理设置 proxy = { 'http':'115.28.5 ...
- TCP/IP TIME_WAIT状态原理
原文转载:http://elf8848.iteye.com/blog/1739571 IME_WAIT状态原理 ---------------------------- 通信双方建立TCP连接后,主动 ...
- SAE J1708 DS36277 MAX3444, DS75176B
http://en.wikipedia.org/wiki/J1708 J1708 SAE J1708 is a standard used for serial communications betw ...
- SCVMM之Windows Server2012 R2新功能
在Windows Server 2012 R2中可以通过使用共享的虚拟硬盘VHDX文件的方法来模拟IP SAN,来为虚拟机创建群集提供共享存储.这样为虚拟机创建群集时就不用再像以前一样通过使用软件模拟 ...
- Microsoft SQL Server 2008 基本安装说明
Microsoft SQL Server 2008 基本安装说明 安装SQL2008的过程与SQL2005的程序基本一样,只不过在安装的过程中部分选项有所改变,当然如果只熟悉SQL2000安装的同志来 ...