需求如下:
对玩家的等级,战斗力,宠物等级建立排行榜, 排行榜显示排名前200的玩家, 而最大显示排名为3000.
方案一: 直接排序
数据结构:
记录玩家属性数据table roleData:
{uid = 1, level = 1, combat = 1, petLevel = 1, rankIndex = {} }
其中rankIndex用于记录玩家在每个榜的位置, key为榜的索引,value为排名.
记录所有玩家属性数据哈希table roleDataHash
key为玩家唯一id,value为roleData.
用于排序的数组table sortTbl, roleDataArray, 同样所有玩家的属性数据roleData
都插入到这里,与roleDataHash共享.
记录每个榜单每个位置对应的玩家id table, rankInfo,
key为榜的索引,value为array table, key为排名,从1开始,value为玩家id.
记录上次排序与这次排序之间发生变化的玩家数据记录table roleDataChangeHash,
key为玩家uid,value为修改的数据的键值对数据,即roleData的 level, combat, petLevel其中的一个或多个.
排序过程:
定时器一小时触发全榜重排一次
- 首先将roleDataChangeHash中有修改的数据同步到玩家自身的roleData中, 同时清空roleDataChangeHash.
- 重排每个榜, 对roleDataHash根据榜单对应的key进行排序,得到降序的新表,遍历这个表,
更新记录每个榜每个位置对应的玩家id(index ==> uid), 更新记录每个玩家在该榜的位置(uid ==> rankIndex).
排序时间复杂度: o(n的平方)
好处:
- 算法简单,有修改的数据先缓存到roleDataChangeHash, 排序前再一次性更新数据.
- 玩家查询自己的排名信息时间复杂度为o(1).
缺点:
- 排序 时间复杂度为n的平方, 玩家账号一旦上规模排序耗时较长,排序时候可能会造成延迟服务,
排序时长有待实际测试.
建议:
- 这种直接排序操作可以单独用一个线程去做, 服务器第一次启动先把所有要排序的玩家数据同步到排行榜线程, 之后有修改的数据先缓存,定时或数据量达到一定程度后再发送到排行榜线程排序.
======================================================