请教大佬,类似蚂蚁森林的能量排行,后端应该怎么设计?

2020-09-09 17:27:57 +08:00
 qwerthhusn

假设系统有 N 万个用户,每个用户都有一个 score 。这个 score 经常发生变化。

需要完成以下功能:

  1. 整个平台,score 最高的 N 个用户的信息
  2. 我的好友 score 排行榜
  3. 我的 score 在整个平台处于的位置

现在没有太好的思路,现在想的是

假设数据存在 MySQL 里面的

create table user (
    id bigint not null primary key,
    name varchar(255) not null,
    score int not null
);

create table user_relation (
   user1_id bigint not null,
   user2_id bigint not null,
   primary key(user1_id, user2_id)
);
5953 次点击
所在节点    程序员
43 条回复
proger
2020-09-10 00:28:44 +08:00
粗浅一点想的话,我感觉一群人分数打架,排出一个总排名表存在一个表内,每当有人分数达到表内到最低分数时,去做表内数据的替换。
这样就变成用户主动去踢榜,可能会比较轻松点。
显示的话,直接显示这个表给所有用户就好了,比较不会需要显示几千上万条数据给用户看,盲猜是百来条的样子。
Olament
2020-09-10 03:13:32 +08:00
一个大小为 N 的最小堆,每当有人的分数达到最小堆顶用户的分数时,弹出最小堆的一个元素,插入这个新用户到最小堆中
Olament
2020-09-10 03:17:12 +08:00
@Olament 看错题目了,尴尬
cassyfar
2020-09-10 04:18:11 +08:00
我个人以前做过推荐,每个商品有一个 score 。当时是线下计算,因为 score 变化不大,每一小时算一次就足够了。

如果 score 变化大而且你需要特别精确的话,可以参考这个:
https://aws.amazon.com/blogs/database/building-a-real-time-gaming-leaderboard-with-amazon-elasticache-for-redis/
xuanbg
2020-09-10 08:56:21 +08:00
凡是排行,统统 Redis 。用一个 ZSet 就行了
SeanLari
2020-09-10 09:35:54 +08:00
这个东西,和游戏的技能使用技能冷却一个意思吧?也就是时间轮?(我不懂我瞎说的
SmiteChow
2020-09-10 09:59:20 +08:00
分数和用户绑定存 mysql,榜单存 redis,定时打榜即可
zdt3476
2020-09-10 09:59:48 +08:00
第 1 点和第三点,redis zset 轻松搞定。至于同步问题也不用担心。更新 mysql 数据的时候同步更新 redis 数据就行了。排行榜这东西本来就不会要求很高的一致性,而且你说的才 N 万用户,那就更不会有问题了。 至于第二点,返回好友列表的 score 给前端,让前端排序。
zdt3476
2020-09-10 10:01:17 +08:00
@zdt3476 或者干脆你查到好友列表的 score 自己排好序再给前端也是一样的。
promise2mm
2020-09-10 10:05:49 +08:00
Redis: 好友排行应该一个 Zset 管够,全部用户的话,考虑数量问题,我的想法是先来个 hash,存 n 个分段的 Zset 的索引 key

比如:key1 -> 1~100 分:Zset1
key2 -> 101~200 分:Zset2
keyN -> X~Y 分:ZsetN

当然,按场景可以调整或者冗余分组的策略,比如按城市(如果需要城市排名的话)
wellsc
2020-09-10 10:09:41 +08:00
@limbo0 海量数据和图数据库有啥关系...不是业务复杂才用图数据库么
qiyuey
2020-09-10 10:17:59 +08:00
推、拉的区别,这种一般拉就行
Citrullus
2020-09-10 10:19:01 +08:00
等一个最优解决方案
676529483
2020-09-10 10:19:47 +08:00
1:大顶堆,每隔一段时间同步下就行
2:因为查询频率不会太高,觉得直接查数据库+缓存就行了
3:跳表,或者直接把 1 的堆分多个,只用找出大概位置就行,比如 5k+
在更新内存数据结构的同时,同步更新数据库
以上瞎说,期待大厂兄弟
ershisi
2020-09-10 10:35:16 +08:00
@optional 同意这个说法。
sdushn
2020-09-10 11:17:14 +08:00
@xiaoliu926 我想到的也是这样,前端做这个更合适,之前遇到一个类似场景,后端推来所有好友数据,前端根据某个字段排序,毕竟这个场景下,可以接受实时性比较差,如果要实时性强的话可能要考虑其他方案了
pepesii
2020-09-10 14:24:11 +08:00
@limbo0 #12 我感觉也是图数据库呢,蚂蚁金服用的是自研的数据库应该是 ocean base,好像有个 gae base
kiwier
2020-09-10 14:31:10 +08:00
@yeqizhang 对,总排名这玩意没人要求实时刷新排名,基本都是各一小时或者几个小时再更新排名
kiwier
2020-09-10 14:32:38 +08:00
@sdushn 好友数据在 app 里本地就存储了,新加或删减好友再同步数据库里
wangyzj
2020-09-10 14:33:25 +08:00
redis zset

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/705551

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX