redis的zset结构具有天然的排序功能,非常适合大并发的排序功能。 排名范围由键值决定,以成员作为排序标识,以分数作为排序依据。 redis排序功能看似简单易用,但在实际应用中却遇到很多问题。 这个功能需要通过适当的操作来设计。接下来我们来梳理一下排行榜的设计思路。
1.排行榜重点设计
排行榜一般按照时间段来分类,包括周排名、月排名和年度排名。 这样,为了区分不同的列表,需要与时间关联起来,通过时间判断将数据保存到对应的zset中。
例如,可以按年份来标识年度列表。 今年的关键是2020年,去年的关键是2019年。月榜以月数来标识。 周榜的情况有点特殊。 zset的key可以根据该天所在的一年中的第几周来确定,这样设置的key为周数时,就可以统计该周的数据。
java中有一种方法可以直接获取周数
请注意音乐音效,星期一设置为一周的第一天,默认为星期日。
Calendar cal = Calendar.getInstance();
//设置周一为一周的第一天
cal.setFirstDayOfWeek(Calenar.MONDAY);
cal.setTime(new Date());
int num = cal.get(Calenar.WEEK_OF_YEAR);
不过,这种方法虽然可以快速获取当天的周数,但有些排名需要查看前一周的数据。 那么上周周列表的关键,就是要得到上一周的周数,就用本周的周数减一即可。
这个时候就出现了一个特殊的情况。 如果今天是今年的第一周,那么前一周的周列表的键就等于0。显然这是不合理的。 那么这种情况应该如何处理呢?
事实上,今年的第 0 周是上一年的最后一周。 您只需要获取上一年最后一周的周数。 所以第一步就是将当前日期向前推7天,然后得到该天所属的周数,这样就可以解决跨年获取周数的问题。
2.Z设置相同的排序规则
在现实生活中,按单一领域排序的排名非常罕见。 这是因为排名中可能存在大量重复分数,导致分数相同时无法确定排名。 这就涉及到第一个问题。 当分数相同时,哪一项数据排在第一位?
实践出真知,打开redis试试吧。 插入6条数据。 分数都是一样的,但是成员不同。 分别是2020001、2020002、2020003、aa、bb、cc。使用zrange排序,结果如下
猜测可能与人物排列顺序有关。 经过查资料验证,当分数值相同时unity玩家分数排行榜,成员按字符顺序排列。
3.ZSet多字段排序
zset只能根据score排序,即单字段排序。 但很多时候有不止一种排序规则。 比如排行榜不仅比较成功关卡的数量unity玩家分数排行榜,还比较通关时间的长短、复活的次数等氛围,这就导致zset的字段远远不够。 那么我们应该如何同时使用多个排序规则呢? 接下来,你需要使用棘手的方法。
由于只有一个排序字段,因此该值会根据排序规则的权重重新分组。 通过将权重高的数值放在组合数的前面来达到数值比较的优点,有点绕,所以我们直接看例子。
场景如下:游戏等级排名按照通关次数倒序排列,按照复活次数倒序排列,按照首次通关时间倒序排列。
文章来源:https://blog.csdn.net/sinat_29774479/article/details/109120432