boost::multi_index 提供一种千人在线即时排行榜的设计思路
原文地址:
http://www.limerence2017.com/2019/06/23/cpp01/
做游戏或金融后台开发,经常会遇到设计开发排行榜的需求。比如玩家的充值排行,战力排行等等。而这种排行基本都是即时更新的,快速排序对于单一类型排序可以满足需求,但是对于多种类的排序就很吃力,比如实现一个排行榜,有战力排序,有充值排序,如下图

快速排序的缺陷
如果用快速排序实现,需要定义四种比较规则,而且qsort排序需要一段连续空间,如数组或者vector,为节约内存,每个元素存储玩家基本信息的指针。之后为每种排行类型定义单独的比较规则。代码如下
1 |
#include <iostream> |
这么做有几个坏处
1 每个排行都要开辟一段连续的序列,即使存储指针也会造成空间的浪费。
2 qsort适合中小数量排序,当人数上千或万以上会造成瓶颈。但是可以通过插入排序优化。
下面提出一种新的结构来处理排序,boost::multi_index 实现了多索引结构,支持按照多个键值排序,可以极大减轻压力。
multi_index 多索引处理排行榜
multi_index 是boost库提出的多索引结构表,可以设定多个主键进行排序,如战力,充值等等,但是必须要有一个唯一主键,我们将player的id设为唯一主键。
为了方便输出我们先完善下PlayerInfo类,重载输出运算符
1 |
//玩家基本信息 |
由于multi_index 各主键排序需要设置比较规则,默认是从小到大,int类型可以用greater, less等。
greater从大到小, less从小到大,也可以自己实现仿函数。
1 |
struct powerOperator |
定义operator()一定要加上const,因为没有修改参数数据。
multi_index 表定义
基于playerinfo实现multi_index表如下
1 |
struct by_id; |
by_id, by_power等都是标签,只需要声明一个结构体,然后tag<标签名>放到索引里。当然可以不带tag,带tag是为了之后获取方便。
powerOperator是定义的战力比较规则,greater定义的充值金额比较规则,是从大到小排序。
multi_index 根据标签获取排序序列
multi_index表在数据插入的时候就根据各个主键排序规则进行排序,所以只需要按照主键取出,获得序列就是排好序的数据。
我们先按照id获取,然后打印输出结果
1 |
auto& ids = con.get<by_id>(); |
结果如下,可以看出是按照id从小到大排序输出的。
1 |
1 1231 10000 |
那我们按照战力获取
1 |
auto& powers = con.get<by_power>(); |
结果能看出是按照战力从大到小输出
1 |
2 22222 2000 |
multi_index 删除数据
删除元素如果是根据唯一主键删除,可以直接删除,如果是非唯一主键,需要查出所有记录并删除。
删除唯一主键为2的玩家
1 |
auto &itfind = ids.find(2);
if (itfind != ids.end()){
|
结果
1 |
after erase: |
插入一条战力重复的数据,并且遍历删除所有战力为1231的玩家
1 |
con.insert(boost::make_shared<PlayrInfo>(4, 1231, 10000)); |
结果
1 |
.................... |
lower_bound 获取的是战力为1231的玩家迭代器的起始值,upper_bound获取的是战力为1231的玩家的最大值的下一个元素。
multi_index 修改数据
修改数据可以用replace,也可以用modify
replace 失败不会删除条目,但是二次copy造成效率低下
modify失败会删除对应条目,容易暴力误删除,但是效率高
replace 找到战力为19999的玩家,并且替换为新的数据。
1 |
auto piter = powers.find(19999); |
下面用modify修改数据
1 |
piter = powers.find(200); |
modify 第一个参数和replace一样,都是要修改的迭代器,第二个参数是一个函数对象,参数类型为表中元素类型。
到目前为止,multi_index介绍完毕,用该多索引结构可以高效实现多级排序,非常适用于即时排行榜。
源码下载
https://github.com/secondtonone1/boost-multi_index-
我的公众号,谢谢关注
boost::multi_index 提供一种千人在线即时排行榜的设计思路的更多相关文章
- 分享一个基于长连接+长轮询+原生的JS及AJAX实现的多人在线即时交流聊天室
实现网页版的在线聊天室的方法有很多,在没有来到HTML5之前,常见的有:定时轮询.长连接+长轮询.基于第三方插件(如FLASH的Socket),而如果是HTML5,则比较简单,可以直接使用WebSoc ...
- 基于JQuery+JSP的无数据库无刷新多人在线聊天室
JQuery是一款非常强大的javascript插件,本文就针对Ajax前台和JSP后台来实现一个无刷新的多人在线聊天室,该实现的数据全部存储在服务端内存里,没有用到数据库,本文会提供所有源程序,需要 ...
- 核心思想:想清楚自己创业的目的(如果你没有自信提供一种更好的产品或服务,那就别做了,比如IM 电商 搜索)
这个时代对于学 IT 的人来说是幸运的.一个普通的程序员可以相对轻易地找到工作,可以轻易拿到比其他行业高得多的工资,甚至自己创建世界级的企业亦非空想.马云.马化腾等企业家的成功,似乎时刻提醒人们:即便 ...
- 一个3D的多人在线游戏, 服务端 + 客户端 【转】
最近学院组织了一个实训,要求是利用Socket通信和D3D的知识, 写一个多人在线的游戏, 服务端是在linux下, 客户是在Windows下: 写这个的目的是想让大家给我找错, 欢迎大家的意见.我的 ...
- 使用boost::multi_index高速构建排行榜
使用boost::multi_index高速构建排行榜 前几天在boost的maillist上看到boost::multi_index将要支持ranked_index(邮件内容见附件2),这实乃我等苦 ...
- 开年巨制!千人千面回放技术让你“看到”Flutter用户侧问题
导语 发布app后,开发者最头疼的问题就是如何解决交付后的用户侧问题的还原和定位,是业界缺乏一整套系统的解决方案的空白领域,闲鱼技术团队结合自己业务痛点在flutter上提出一套全新的技术思路解决这个 ...
- 负载均衡--大型在线系统实现的关键(上篇)(再谈QQ游戏百万人在线的技术实现)
http://blog.csdn.net/sodme/article/details/393165 —————————————————————————————————————————————— 本文作 ...
- 关于智普 - 千人免费学|Python培训|国内最权威python培训|html5
关于智普 - 千人免费学|Python培训|国内最权威python培训|html5 智普教育隶属于北京顶嵌开源科技有限公司,成立于2008年. 智普开源是基于Linux系统的互联网开源学习平台,讲求务 ...
- 网页版Rstudio︱RStudio Server多人在线协作开发
网页版Rstudio︱RStudio Server多人在线协作开发 想了解一下RStudio Server,太给力的应用,可以说成是代码分布式运行,可以节省时间,放大空间. RStudio是一个非常优 ...
随机推荐
- zoj 4122 Triangle City 2019山东省赛J题
题目链接 题意: 给出一个无向图,类似三角形的样子,然后给出边的权值,问找一条从第一个点到最后一个点的路径,要求每一条边只能走一次,并且权值和最大,点可以重复走. 思路: 首先观察这个图可以发现,所有 ...
- c++字符和字符串转整数类型及大小端
在网络传输中,很多数据都是按字节传递而不是字符串.最近就遇到了这个问题,在刚开始学c语言时都没有问题,可能太久不用了,记录一下 在报中文,用2个字节hex码来表示报文正文长度,什么是hex码呢 就是1 ...
- [BZOJ 1095] [ZJOI2007]Hide 捉迷藏——线段树+括号序列(强..)
神做法-%dalao,写的超详细 konjac的博客. 如果觉得上面链接的代码不够优秀好看,欢迎回来看本蒟蒻代码- CODE WITH ANNOTATION 代码中−6-6−6表示左括号'[',用−9 ...
- 2. SaltStack数据系统: Grains、Pillar
1. SaltStack数据系统 Grains (谷物) Pillar (支柱) 2.Grains Grains存放着Salt命令启动时收集的信息,运行时不收集 2.1 信息查询 收集资产 网卡,i ...
- [旧版] CASthesis 模板编译的问题
写在前面的话:国科大最新版的模板在这里(https://github.com/mohuangrui/ucasthesis),利用它来写博后出站报告的相关介绍在这里: 本篇博文是针对另一个模板进行介绍的 ...
- MessagePack Java 0.6.X 多种类型变量的序列化和反序列化(serialization/deserialization)
类 Packer/Unpacker 允许序列化和反序列化多种类型的变量,如后续程序所示.这个类启用序列化和反序列化多种类型的变量和序列化主要类型变量以及包装类,String 对象,byte[] 对象, ...
- fflush函数
/*** flush.c ***/ #include<stdio.h> #include<string.h> #include<stdlib.h> int main ...
- Codeforces Round #567 (Div. 2) E2 A Story of One Country (Hard)
https://codeforces.com/contest/1181/problem/E2 想到了划分的方法跟题解一样,但是没理清楚复杂度,很难受. 看了题解觉得很有道理,还是自己太菜了. 然后直接 ...
- ARTS打卡计划第二周
Algorithms: https://leetcode-cn.com/problems/3sum/ 算法是先排序,然后按照两个数和两边逼中,考虑去重. Review: https://www.inf ...
- canvas基础知识点(一)
给canvas设置宽高: canvas标签的宽高默认是300*150,是一个行内块元素 可以在canvas标签上通过width,height来设置 可以在js中给dom对象设置: mycanvas.w ...