redis实现排行榜,解决同分问题

redis排行榜

需求

如果一个需求是类似王者荣耀的巅峰赛排行榜, 同分的情况下我们如果想让先到同分的那一个排前面怎么办.

解决方案

我是将获取第二年的一月的时间戳乘于1000000, 然后-去当前时间戳乘于1000000给同分加上小数, 这样就解决了同分的问题
上代码:

import math
import time

from redis import StrictRedis
from retry import retry

sort_manager = StrictRedis(host="127.0.0.1", port=6379, db=0, password="",
                           decode_responses=True)

@retry(tries=10, delay=0.01)
def add_score_redis(control_key: str, user_uuid: str, score: float):
    """
    添加分数排行榜
    :param control_key: 排行榜的key
    :param score: 分数
    :param user_uuid: 用户的uuid
    :return: None
    """
    old_score = sort_manager.zscore(control_key, user_uuid)
    if old_score:
        if math.floor(old_score) < math.floor(score):
            sort_manager.zadd(control_key, {user_uuid: score})  # 更新分数
            return
        return
    if not old_score:
        sort_manager.zadd(control_key, {user_uuid: score})  # 添加分数
        return


def get_score_list(control_key: str, start: int = 0, end: int = -1, show_scores: bool = False) -> list:
    return sort_manager.zrevrange(control_key, start, end, withscores=show_scores)


def get_user_ranking(control_key: str, user_uuid: str) -> list:
    """
    获取自己的排名
    :param control_key:
    :param user_uuid:
    :return: [排名, 分数]
    """
    return [sort_manager.zrevrank(control_key, user_uuid), sort_manager.zscore(control_key, user_uuid)]

def get_float_score(end_time: int, score: int) -> float:
    """
    返回浮点数的分数
    :param end_time: 结束时间的排行榜
    :param score: int 分数
    :return: float 分数
    """
    end_float_str = "0." + str(end_time * 1000000 - int(time.time() * 1000000))
    return float(score) + float(end_float_str)

if __name__ == '__main__':
    control_key = "socre_ranking"
    SOCRE_END_TIME = 1672502400  # 2022年排行榜
    # 两个同分, 排序肯定是按照先入的排前面
    add_score_redis(control_key, "1", get_float_score(SOCRE_END_TIME, 100))
    add_score_redis(control_key, "2", get_float_score(SOCRE_END_TIME, 100))
    add_score_redis(control_key, "3", get_float_score(SOCRE_END_TIME, 101))
    add_score_redis(control_key, "4", get_float_score(SOCRE_END_TIME, 100))
    print("-----获取个人排名-----这里返回的第一名是[0,分数] 所以你的索引要加一")
    print(get_user_ranking(control_key, "2"))
    print(get_user_ranking(control_key, "4"))
    print("-----获取一段范围的排名------")
    print(get_score_list(control_key, 0, 1, True))  # 这个已经是排好序了的 后面自己用math.floor向下去就OK
    print(math.floor(100.99999999999999))


版权声明:本文为qq_41929657原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。