如何设计微信运动的排行榜功能
腾讯二面的场景题,设计微信运动的排行榜,使用 Redis 的 Zset 数据结构来实现。
下面是我自己的分析,欢迎交流和补充,你提的更多问题,我会添加到文章中,提供给大家去思考。
需求分析:
1.存储所有用户的微信步数,使用什么结构,key value 分别是啥?
因为要存储每一天的数据,key 可以是:业务名称加上日期,value 是用户的 ID、score 就是对应的步数。
2.不同用户有不同的好友,每个人要单独实现一个排行榜吗?
不用,只需要维护一个排行榜,每一个用户都有自己的好友列表,可以用 Set 来存储,拿到好友列表之后,通过 ZScore 拿到好友 ID 的步数,排序之后返回给前端。
3.相同步数的还有如何排序?微信可能不太重要,但是在游戏中,相同的分数或者王者多少颗星,如果排序呢?
给分数 score 赋值的时候可以带上一个时间戳,这样就不会有相同的 socre 存在了。排序的时候也就解决了这个问题。
数据结构设计 每日使用一个 Zset 来存储用户当天的步数。
key 设计: step_rank:{date} 比如 step_rank:20254003.
微信运动的排行榜对于业务的场景并不是要求实时的,比如间隔五分钟去实现更新。 可以将步数先放入到消息队列中, Zadd key member value 或者累加操作等,实现排行榜的变化。
冷热数据隔离
Redis 的内存容量也是有限的,不能直接存储所有天数的数据。可以保留近三天的数据,对于历史的数据都是固定了,可以保存到数据库里面去,在每天晚上的时候自动将三天前的数据备份到数据库中。
详细细节:
好友排行榜生成:
1.每一个用户好友都用 Set 存储,key 为 friends:{userId}
1.获取用户123的所有好友ID
SMEMBERS friends:user123
批量的拿到好友的分数 拿到friend1和friend2的分数
ZSCORE step_rank:20231001 friend1
ZSCORE step_rank:20231001 friend2
查询出来分数存储到集合中在后端排序完成之后返回给前端进行展示
问题
1.如果数据量很大,底层的效率如何保证呢?
通过 哈希表+跳表来实现, 通过哈希表 O1 的时间复杂度找到跳表中的位置。
跳表不需要平衡树那样需要平凡的重新位置平衡,只是需要更新局部节点。
异步批量的跟新,通过消息队列实现异步更新。
#排行榜##RedisZ#牛牛的面试专栏,希望自己在25年可以拿到一份大厂的SP Offer 你的点赞和收藏都是我持续更新的动力