一文设计亿级redis实时排行榜
设计高并发实时排行榜所需redis基础
redis四大统计
基数统计
基数 / Cardinality 是指集合中不同的元素的数量,简单来说,就是去重后的个数。
二值统计
二值统计是指将数据分为两个类别或状态,成功失败这样的,并对这些数据进行计数和分析。
排序统计
排序统计涉及将数据按照一定的顺序(升序或降序)进行排序,以便分析比较。
聚合统计
将多个数据记录组合成一个集合,并对该集合进行数值特征的计算统计。
Redis的有序集合 Sorted Set
语法:
- ZADD / 向有序集合添加一个或多个成员,或者更新已经存在成员的分数
1
ZADD key score member [score member ...]
- ZSCORE / 获取有序集合中指定成员的分数
1
ZSCORE key member
- ZINCRBY / 为有序集合中已存在的成员分数加上一个增量值
1
ZINCRBY key increment member
- ZRANK / ZREVRANK 获取有序集合中指定成员的排名。ZRANK是升序排名,ZREVRANK是降序排名。
1
2
ZRANK key member
ZREVRANK key member
- ZRANGE / ZREVRANGE 获取有序集合中指定区间的成员,ZRANGE是按分数从小到大排序,ZREVRANGE是按分数从大到小排序
1
2
ZRANGE key start stop [WITHSCORES]
ZREVRANGE key start stop [WITHSCORES]
- WITHSCORES / 返回携带值
- ZCOUNT / 获取有序集合中指定分数区间的成员数量
1
ZCOUNT key min max
- ZREM / 移除有序集合中的一个或多个成员
1
ZREM key member [member...]
- ZCARD / 获取有序集合的成员数
1
ZCARD key
- ZREMRANGEBYSCORE / 移除有序集合中给定分数区间的所有成员
1
ZREMRANGEBYSCORE key min max
游戏玩家排行榜–积分制排行榜
在一个多人在线游戏中,我们希望能够实时追踪和显示玩家的排行榜,在高并发场景下,我们该佮设计能够承载频繁修改的排行榜呢?如果我们希望排行榜是实时更新的,在高并发下,后台的压力的非常巨大的。
现在的需求是这样的,需要周期更新的日榜、周期更新的周榜、实时更新的总榜。对于这三种不同类型的排行榜,采用不同的三种最合适的设计来满足不同的需求。
日榜
日榜的更新频率比较频繁,需要redis提高并发性,但是数据量比较少,不需要入库。所以设计方案是redis提供读写。
那如何实现周期更新呢?系统配置有更新排行榜的时间,比如00:00。日榜的key值这样设计:platform+type+time。这样新的一天的数据更新就不会影响到昨天的数据。当redis内缓存了太多的数据,可以删除一些老的日榜数据。
周榜
周榜是写少读多,对实时性要求不高,不需要redis来承载高并发量的访问,故周榜使用mysql实现即可。周榜库表的设计和日榜redis比较类似,表名:platform+type+time。字段持有用户id,用户在time范围内获得的积分。
前端想要获得周榜,就拿对应的时间来查表即可。比如想要那上一周的周榜,后端会计算上一周对应的time,然后去查表得到前100名的用户数据,然后返回前端
总榜
总榜的特点是实时性,和周期性更新不同,对实时的要求很高。同时总榜不比日榜,对数据量的要求也大。不能只拿redis来负责,需要使用redis+mysql来实现。
mysql的库表非常简单,不需要对time进行多表处理。redis负责缓存前100名的排行榜,mysql负责储存所有用户的排行榜。redis如何知道自己的前一百名排行榜数据脏了呢?每局游戏胜利后,在向数据库写入前,会查看当前用户的积分是不是比第一百名的大,如果是,说明前一百名发生变动,需要把redis的数据设置为脏。
到此三种榜单便全部设计完成
后续更新滚动榜等的实现