# game-ranking **Repository Path**: importguitar/game-ranking ## Basic Information - **Project Name**: game-ranking - **Description**: 游戏排行榜系统 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2022-07-31 - **Last Updated**: 2023-02-16 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 排行榜 ## 先看下效果 我造了一些数据,存入Redis,生成排行榜,有近三百万条: ![](./src/main/resources/static/排行榜中的玩家数量.png) 查询玩家排名信息接口,响应速度优秀: ![](./src/main/resources/static/查询玩家前后10名玩家.png) ## 设计 ### 图示 ![](http://assets.processon.com/chart_image/62e679b67d9c08072e6d56cc.png) ### 说明 #### 重点需求分析 **日活跃用户在10万⼈以上** 数据量较大,不能直接使用MySQL排序,影响用户体验 证明: 不使用索引: ![](./src/main/resources/static/MySQL排序大量数据(不使用索引).png) 对于上边SQL,MySQL优化器确实没有选择索引: ![](./src/main/resources/static/MySQL优化器未选择索引.png) 数据量大,需要回表,使用索引反而更慢 ![](./src/main/resources/static/MySQL排序大量数据(强制使用索引).png) 所以,需要借助Redis的zset **在每月活动结束之后,需要依据这⼀活动总分,从高到低为玩家建立排行榜** - 不要求实时,可以在活动结束后生成排行榜,节省内存 - 每月都有活动,key上应该做出区分,这样可以即时清理上一个月的数据。key设计为:固定前缀 + 活动id **如果多位玩家分数相同,则按得到指定分数顺序排序,先得到的玩家排在前面** zset的score需要由玩家得分和时间两部分组成 整数部分是玩家得分 小数部分是玩家分数最后更新时间的倒数 * 一个相对固定值 #### 代码实现 见代码 #### 测试 我造了一些数据,存入Redis,生成排行榜,有近三百万条: ![](./src/main/resources/static/排行榜中的玩家数量.png) 查询玩家排名信息接口,响应速度优秀: ![](./src/main/resources/static/查询玩家前后10名玩家.png) 相同分数,按照时间先后排序: ![](./src/main/resources/static/相同分数按照时间先后排序.png) #### 思考 1.目前的实现方式,在生成排行榜时比较耗费时间: ![](./src/main/resources/static/生成排行榜耗时.png) - 可以改为多线程,会有一定缓解,但数据量较大,整体应该还会较慢 - 或者一开始就存入Redis,后续也更新Redis,即活动期间动态更新排行榜,优势是可以实时更新,弊端就是太占用内存 2.排行榜的创建时机 - 可以监听活动结束的消息,触发创建 - 如果每月活动的结束时间都相同,也可采用定时任务