好好的 Tair 排行榜不用,非得自己写?20 行代码实现高性能排行

p_wdn
发布于 2022-5-26 18:03
浏览
0收藏

 

TairZset 是阿里云自研的可实现任意维度 double 类型的分值排序的数据结构,借助 Tair 自研客户端同时可实现扩展性,即可以将计算任务分布至多个数据节点完成,实现分布式排行榜能力。本文介绍了 TairZset 的能力以及利用 TairZset 实现奖牌榜、分布式排行榜、实时排行榜的方案。
 

一、背景介绍

 

排序需求常见于各类游戏、应用、奖牌、积分等排行榜中,通常业务对排序的需求如下:

 

  • 支持增删改查和反向排序,可根据分数范围获取相应用户。
  • 排序操作执行速度快。
  • 支持多维排序。
  • 支持扩展(即 分布式排行榜 )。在数据分片容量或计算能力不足时,可以将其扩展到其他数据分片。

 

二、TairZset介绍

 

原生 Redis 支持的排序结构 Sorted Set(也称Zset)只支持一个 double 类型的分值排序,实现多维度排序时较为困难。例如通过IEEE 754结合拼接的方式实现多维度排序,此类方式存在实现复杂、精度下降、ZINCRBY命令无法使用等局限性,借助阿里云自研的 TairZset 数据结构,可帮助您轻松实现多维度排序能力,相较于传统方案具有如下优势:

 

  • 支持任意维度的 double 类型的分值排序(排序优先级为从左往右)。
  • 支持 ZINCRBY 命令,不再需要取回当前数据,在本地增加值后再拼接写回 Redis。
  • 支持和原生 Zset 类似的所有 API。
  • 客户端适配简易,无需任何编解码封装。
  • 提供 普通排行榜 和 分布式排行榜 能力。

 

三、通过 TairZset 实现奖牌榜

好好的 Tair 排行榜不用,非得自己写?20 行代码实现高性能排行-鸿蒙开发者社区

注:数据仅做演示使用

 

在奖牌榜中,首先按照金牌排名,如果金牌相等,则按照银牌,否则继续按照铜牌。在上述数据中,E 和 F 金牌数相等,但是银牌数 E 大于 F,因此 E 排名靠前,多维排序天然被 TairZset 支持,用户只需要使用简单的 API 即可完成。

 

1.首先依赖 Tair 客户端 alibabcloud-tairjedis-sdk (https://github.com/aliyun/alibabacloud-tairjedis-sdk)

<dependency>
    <groupId>com.aliyun.tair</groupId>
    <artifactId>alibabacloud-tairjedis-sdk</artifactId>
    <version>1.6.0</version>
</dependency>

 

2.创建排行榜,添加数据并排序。

JedisPool jedisPool = new JedisPool();
// 创建排行榜
LeaderBoard lb = new LeaderBoard("leaderboard", jedisPool, 10, true, false);

// 如果金牌数相同,按照银牌数排序,否则继续按照铜牌
//                    金牌 银牌 铜牌
lb.addMember("A",     32,  21, 16);
lb.addMember("D",     14,  4,  16);
lb.addMember("C",     20,  7,  12);
lb.addMember("B",     25,  29, 21);
lb.addMember("E",     13,  21, 18);
lb.addMember("F",     13,  17,  14);

// 获取 A 的排名
lb.rankFor("A"); // 1

// 获取top3
lb.top(3);
// [{"member":"A","score":"32#21#16","rank":1}, 
// {"member":"B","score":"25#29#21","rank":2}, 
// {"member":"C","score":"20#7#12","rank":3}]

// 获取整个排行榜
lb.allLeaders();
// [{"member":"A","score":"32#21#16","rank":1}, 
// {"member":"B","score":"25#29#21","rank":2}, 
// {"member":"C","score":"20#7#12","rank":3}, 
// {"member":"D","score":"14#4#16","rank":4}, 
// {"member":"E","score":"13#21#18","rank":5}, 
// {"member":"F","score":"13#17#14","rank":6}]

 

四、通过TairZset实现分布式排行榜

 

实现分布式排行榜有两种做法,分别为精确排名法和非精确排名法(线性差值法),下面分别介绍两种方法:

好好的 Tair 排行榜不用,非得自己写?20 行代码实现高性能排行-鸿蒙开发者社区

实现同一基本功能时,普通排行榜和分布式排行榜的实现方案如下:

 

说明:此处分布式排行榜采用精确排名法实现, 通过多个 TairZset 来保存数据在不同的分片上。

好好的 Tair 排行榜不用,非得自己写?20 行代码实现高性能排行-鸿蒙开发者社区

五、通过TairZset实现实时、小时、日、周和月维度的排行榜

 

该场景下的需求是实现月榜,那么这个Key就从月的维度进行索引,利用 TairZset 的多级索引能力可以轻松实现不同时间范围的排行榜。本案例中,月度的所有数据存储在一个 Key 中(名称为 julyZset),写入演示数据如下:

exzincrby julyZset 7#2#6#16#22#100 7#2#6#16#22_user1 
exzincrby julyZset 7#2#6#16#22#50 7#2#6#16#22_user2 
exzincrby julyZset 7#2#6#16#23#70 7#2#6#16#23_user1 
exzincrby julyZset 7#2#6#16#23#80 7#2#6#16#23_user1

 

说明:

  • 7#2#6#16#22#100表示7月第2周6号16点22分,更新其分数为100。
  • 7#2#6#16#22_user1表示此时间点更新的用户,用户名加入了具体时间前缀。

好好的 Tair 排行榜不用,非得自己写?20 行代码实现高性能排行-鸿蒙开发者社区
六、总结

 

本文介绍了常见排行榜方案,并介绍了 TairZset 的功能,实现了奖牌榜,分布式排行榜,以及时间维度的各类榜单,在性能高效的同时也帮助用户解决了实际的业务问题,欢迎大家使用交流。

 


参考:
[1] alibabacloud-tairjedis-sdk: https://github.com/aliyun/alibabacloud-tairjedis-sdk
[2] 线性差值法:https://zh.wikipedia.org/zh-hans/线性差值

 

文章转自公众号:阿里云数据库

分类
标签
已于2022-5-26 18:03:49修改
收藏
回复
举报
回复
    相关推荐