【100万用户量“排行榜列表”和“我的排名”功能优化记录】

news/2025/2/13 15:41:04/

100万用户量“排行榜列表”和“我的排名”功能优化记录

    • 前言背景:
    • 难点:
    • 解决过程:
    • mongodb小坑:
    • 总结优化过程:
    • 最后:
    • 参考:

前言背景:

最近做一个预算100万用户量的项目,需要优化,尤其是“排行榜列表”和“我的排名”功能。比较判定的逻辑是:

“排行榜列表”:
分数倒序,用时升序,用户ID升序

“我的排名”:(
(分数 < 我的分数)
|| (分数 = 我的分数 && 时间 < 我的时间)
|| (分数 = 我的分数 && 时间 = 我的时间 && 用户ID < 我的ID)
)

难点:

"or"查询无法触发索引

解决过程:

一开始尝试的数据库索引优化,结果效果不理想。
然后尝试把数据取出到php处理,结果内存爆满(其实该方法只适合数据计算较复杂的逻辑,数据量大的情况不合适);
然后采用redis加锁查数据库存缓存定时过期刷新的方法,结果客户说要即时的(而且这个方法也优化不了“我的排名”,只能优化“排行榜列表”);
然后采用mongodb,芒果有提供类似mysql一样的排序查询语句,可以直接在数据库里面处理,而芒果数据是在缓存里面的,所以可以直接在缓存里面执行语句,速度嘎嘎快,解决了“排行榜列表”的即时需求和性能问题,但是“我的排名”消耗依然高,因为不管是mysql还是mongodb,“or”都是不能触发索引的,哪怕芒果数据是在缓存里,100万数据不用索引也够呛。
然后采用分表的方法,由于游戏比较简单,所以估计80-100分的人居多,所以按这样分表(0-80,80-85,85-90,90-95,95-100),在设个冗余表,记录每个分表的总数。插入数据时,根据分数范围插入对应表和在对应分表总数加一,查询“我的排名”时,根据我的分数查找对应分表,计算我在该分表的排名,加上前面分表的总数,算出我的总排名。大功告成!

mongodb小坑:

用php这种弱类型语言插入数字很可能被识别为字符串,从而排序出现问题

总结优化过程:

索引 -> php代替mysql计算 -> redis -> mongodb -> 分表+冗余表

最后:

分表的优化操作有点麻烦,就去磨了一下产品,砍掉了“我的排名”需求哈哈哈,所以这个分表操作最终没有落地,但理论上应该是可行的。所以最终是用mongodb实现了“排行榜列表”的优化,用砍产品的方式实现了“我的排名”优化哈哈。
一直以为redis已经能处理大部分的单机优化了,直到遇到了100万用户量的排行榜和我的排名这样的需求,数据库排序消耗太大,加索引也不行,取到php处理,php内存消耗也大,redis不能做多条件的排序(比如分数倒序,时间升序,id升序按这三个条件来排,redis就做不到),最后就用上了mongodb,这个以为已经被淘汰的工具。

参考:

https://www.php.net/manual/zh/book.mongodb.php php的mongodb原生驱动
https://www.mongodb.com/docs/v4.2/crud/ mongodb官方文档
https://www.yisu.com/zixun/39612.html php封装mongodb
https://www.php.cn/php-weizijiaocheng-405982.html php的mongodb操作
https://www.kancloud.cn/noahs/linux/1425616 用户权限操作


http://www.ppmy.cn/news/191593.html

相关文章

凉了呀,面试官叫我设计一个排行榜。

这是why哥的第89篇原创文章 前两天&#xff0c;有一个读者给我发了一张图片。 我问&#xff1a;发什么肾么事了&#xff1f; 于是有了这样的对话&#xff1a; 他发的图&#xff0c;就是微信运动步数排行榜的截图&#xff1a; 其实扯了这么多&#xff0c;这就是个常见的面试场景…

微信小游戏排行榜功能快速开发教程

要做这个好友排行榜.必然要有好友的战绩比分,然后再做排序,最后将数据呈现在UI上 , 可以分为下面几个步骤: 保存每个用户的分数获取好友列表,并获取好友的分数渲染排行榜 保存每个用户的分数 保存每个用户的分数,需要调用微信的云存储API,将用户的分数持久化的存起来 . // 保…

Redis结合业务逻辑实现排行榜

文章目录 前言实现个人总结附加信息缓存问题删除问题排序问题 测试demo 前言 大家好&#xff0c;我又回来了。已经好久没有写博客了&#xff0c;今天要写的排行榜的需求&#xff1a;排名前50&#xff0c;然后标记自己的位置&#xff0c;如果超过就补到后面去。 其实实现很简单…

golang笔记:游戏中排行榜的实现

date: 2017-08-29 title: “golang笔记&#xff1a;游戏中排行榜的实现” draft: false categories: golanggame tags:golanggame thumbnailImagePosition: left 原文地址https://github.com/liyiheng/blog-gen 游戏开发中排行榜经常出现,接触过的排行榜有两种。一种是由玩家挑…

使用Redis构建高效稳定低延迟的排行榜业务

一、业务描述 现有一排行榜业务&#xff0c;数据库中拥有百万级用户&#xff0c;中秋佳节将要来临&#xff0c;用户可以写一篇关于中秋的故事&#xff0c;故事可邀请好友点赞&#xff0c;也可以打赏该故事&#xff0c;现在要挑选出关于中秋话题相关的故事&#xff0c;根…

PyFlink 有状态流处理实例 实时排行榜

01 UDAF 聚合函数的使用 自定义聚合函数&#xff08;UDAF&#xff09;&#xff0c;将多条记录聚合成一条记录。其输入与输出是多对一的关系&#xff0c;即将多条输入记录聚合成一条输出值。 需要注意的是&#xff1a;当前聚合函数仅在流模式下的 GroupBy 聚合和 Group Window…

排行榜奖励发放

一般来说排行榜奖励都通过邮件来发放&#xff0c;要不就是对于在线用户直接发给用户自身&#xff0c;对于离线用户发到用户的离线邮箱&#xff0c;用户上线可以通过邮件取到。这样做简单直接&#xff0c;易于处理&#xff0c;也不容易出错&#xff0c;但是在用户很多的时候可能…

字节跳动系统设计面试实时排行榜

题目 现在有个游戏&#xff0c;有亿级别的用户会来玩&#xff0c;玩游戏后会获得一个分数&#xff0c;当游戏结束的时候返回给用户自己所在的排名和排名前百分比&#xff0c;如何设计这样一个系统。 思路 功能其实并不算复杂&#xff0c;有很多种方式可以实现&#xff0c;所…