基于redis数据结构ZSET实现邀请人排行榜

基于Redis ZSET实现邀请人排行榜

基于redis数据结构ZSET实现邀请人排行榜

  1. 背景:用户注册可以填写邀请人id,系统记录邀请人排行情况
  2. 方案:因为ZSET是一个天然有序的数据结构,我们可以把积分当做score,userId当做member,放到zset中,zset会默认按照SCORE进行排序的。
  3. 代码实现

maven依赖

        <!--    Redisson    -->
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson-spring-boot-starter</artifactId>
            <version>3.24.3</version>
        </dependency>
    //用户注册
    //更新排名(inviterId邀请人ID)
    updateInviteRank(inviterId);

updateInviteRank的具体代码实现:

//定义RScoredSortedSet对象
private RScoredSortedSet<String> inviteRank;
//初始化
@Override
public void afterPropertiesSet() throws Exception {
    this.inviteRank = redissonClient.getScoredSortedSet("inviteRank");
}

private void updateInviteRank(String inviterId) {
    // 如果邀请者ID为空,则直接返回,不进行操作
    if (inviterId == null) {
        return;
    }
    // 获取Redisson的锁对象
    RLock rLock = redissonClient.getLock(inviterId);
    // 对邀请者ID对应的锁进行加锁操作,避免并发更新
    rLock.lock();
    try {
        // 获取邀请者的当前排名分数
        Double score = inviteRank.getScore(inviterId);
        // 如果当前分数为空,则设置默认为0.0
        if (score == null) {
            score = 0.0;
        }
        // 将邀请者的排名分数增加100.0,并更新到排行榜中
        inviteRank.add(score + 100.0, inviterId);
    } finally {
        // 最终释放邀请者ID对应的锁
        rLock.unlock();
    }
}

RScoredSortedSet提供了很多方法方便对ZSET进行操作,以下是一些常用的排行方法:

  • Double getScore(V var1); 获取指定成员的分数。
  • boolean add(double var1, V var3); 向有序集合中添加一个成员,指定该成员的分数。
  • Integer rank(V var1); 获取指定成员在有序集合中的排名(从小到大排序,排名从 0 开始)。
  • Integer revRank(V var1);获取指定成员在有序集合中的排名(从大到小排序,排名从 0 开始)。
  • Collection<ScoredEntry> entryRange(int var1, int var2); 获取分数在指定范围内的成员及其分数的集合。

获取前N个用户的排名信息

//按照分数从高到低,获取前N个用户的排名信息
public List<InviteRankInfo> getTopN(Integer topN) {
    Collection<ScoredEntry<String>> rankInfos = inviteRank.entryRangeReversed(0, topN - 1);

    List<InviteRankInfo> inviteRankInfos = new ArrayList<>();

    if (rankInfos != null) {
        for (ScoredEntry<String> rankInfo : rankInfos) {
            InviteRankInfo inviteRankInfo = new InviteRankInfo();
            String userId = rankInfo.getValue();
            if (StringUtils.isNotBlank(userId)) {
                User user = findById(Long.valueOf(userId));
                if (user != null) {
                    inviteRankInfo.setNickName(user.getNickName());
                    inviteRankInfo.setInviteCount(rankInfo.getScore().intValue() / 100);
                    inviteRankInfos.add(inviteRankInfo);
                }
            }
        }
    }
    return inviteRankInfos;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值