1. 前言
前段时间刚为项目(手游)实现了一个实时排行榜功能, 主要特性:
数据量不大, 大致在 1W ~ 50W区间(开服,合服会导致单个服角色数越来越多).
2. 排行榜分类
按照排行主体类型划分英雄联盟战力指数查询, 主要分为:
该项目是个坦克手游, 大致情况是每个角色有N辆坦克, 坦克分为多种类型(轻型, 重型等), 玩家可加入一个军团(公会).
具体又可以细分为:
- 战斗力排行榜(1. 战斗 2.等级)
- 个人竞技场排行榜(1. 竞技场排名)
- 通天塔排行榜(1.通天塔层数 2.通关时间)
- 威望排行榜(1.威望值 2.等级)
- 军团等级排行榜(1.军团等级 2.军团总战斗力)
- 中型
- 重型
- 反坦克炮
- 自行火炮
↑ 括号内为排序维度
3. 思路
基于实时性的考虑, 决定使用Redis来实现该排行榜.
文章中用到的redis命令如有不清楚的, 可参照 Redis在线手册 .
需要解决如下问题:
复合排序(2维)排名数据的动态更新如何取排行榜4. 实现 复合排序
基于Redis的排行榜主要使用的是Redis的 有序集合()来实现
添加 成员-积分 的操作是通过Redis的zAdd操作
ZADD key score [[score ] [score ] ...]
默认情况下, 若score相同, 则按照 的字典顺序排序.
4.1 等级排行榜
首先以等级排行榜(1. 等级 2.战力)为例, 该排行榜要求同等级的玩家, 战斗力大的排在前. 因此分数可以定为:
分数 = 等级* + 战斗力
游戏中玩家等级范围是1~100, 战力范围0~.
此处设计中为战斗力保留的值范围是 10位数值,等级是 3位数值英雄联盟战力指数查询, 因此最大数值为 13位 .
有序集合的score取值是是64位整数值或双精度浮点数, 最大表示值是 , 即能完整表示 18位 数值,因此用于此处的 13位score 绰绰有余.
4.2 通天塔排行榜
另一个典型排行榜是 通天塔排行榜(1.层数 2.通关时间) , 该排行榜要求通过层数相同的, 通关时间较早的优先.
由于要求的是通关时间较早的优先, 因此不能像之前那样直接 分数=层数*10^N+通关时间 .
我们可以将通关时间转换为一个相对时间, 即 分数=层数*10^N + (基准时间 - 通关时间)
很明显的, 通关时间越近(大), 则 基准时间 - 通关时间 值越小, 符合该排行榜要求.