当前位置: 首页> 财经> 股票 > 招聘网站大全_百度推广四川成都地区服务中心_杭州seo网站推广_河南网站定制

招聘网站大全_百度推广四川成都地区服务中心_杭州seo网站推广_河南网站定制

时间:2025/7/9 10:52:22来源:https://blog.csdn.net/qq_41712271/article/details/142747064 浏览次数:0次
招聘网站大全_百度推广四川成都地区服务中心_杭州seo网站推广_河南网站定制

Redis 实现排行榜主要依赖于其有序集合zset(Sorted Set)数据结构。

zset中可以存储不重复的元素集合,并为每个元素关联一个浮点数分数(score),Redis 会根据这个分数自动对集合中的元素进行排序。

可以使用 `ZADD` 命令来向有序集合中添加元素,将上面列表中:用户id作为元素、积分作为分数

获取用户积分排行
使用 `ZREVRANGE` 命令(从高到低排序)或 `ZRANGE` 命令(从低到高排序)来获取排行榜的前几名

# 积分相同时,按最后更新时间升序,解决思路

可以将zset中的score设置为一个浮点数,其中整数部分为积分,小数部分为最后更新时间时间戳,算法如下

## score = 积分 + 时间戳/10的13次方

> 这里为什么要除以10的13次方?由于时间戳的长度是13位,除以10的13次方,可以将其移到小数点的右边

对上面表格,处理之后,变成了下面这样

| 用户id | 积分 | 最后更新时间时间戳(毫秒) | score |
| ------ | ---- | ------------------------ | ----------------- |
| user1 | 100 | 1720663200002 | 100.1720663200002 |
| user2 | 100 | 1720663200001 | 100.1720663200001 |
| user3 | 150 | 1720663200000 | 150.1720663200000 |

按score降序排序后,是:user3 (150.1720663200000) > user1 (100.1720663200002) > user2( 100.1720663200001)

和预期的不一样,user2的最后更新时间是小于user1的,user2应该排在user1之前,怎么办呢

需要再做一次转换

## score = 积分 + (1 - 时间戳/10的13次方)

处理后,表格变成了下面这样

| 用户id | 积分 | 最后更新时间时间戳(毫秒) | score |
| ------ | ---- | ------------------------ | ----------------- |
| user1 | 100 | 1720663200002 | 100.8279336799998 |
| user2 | 100 | 1720663200001 | 100.8279336799999 |
| user3 | 150 | 1720663200000 | 150.8279336800000 |

按降序排序后,是:user3 (150.8279336800000) > user2 (100.8279336799999) > user1(100.8279336799998)

这样就达到了预期的目的

 





具体实现代码如下
1 pojo类

@Data
public class UserPointsReq {//用户idprivate String userId;//积分private Integer points;//最后更新时间(时间戳毫秒)private Long updateTime;
}/////返回结果封装
@Data
public class UserRanking {private String userId;private double redisScore;
}

2 核心代码

import com.example.demo_26.redis_paiming.dto.UserPointsReq;
import com.example.demo_26.redis_paiming.dto.UserRanking;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;/*** 用户积分排行榜控制器* <p>* 该控制器提供了用户积分的插入和查询用户积分排行榜的功能* 使用Redis的有序集合(ZSet)来存储用户积分,以实现高效查询和排序* </p>*/
@RestController
public class UserRankingController {public static final String redis_key="user:ranking";@Autowiredprivate StringRedisTemplate stringRedisTemplate;/*** 用户积分批量插入到Redis** @param userPointsReqList 包含用户积分和更新时间的列表* @return 总是返回true,表示操作成功*/@PostMapping("/addUserPoint")public boolean addUserPoint(@RequestBody List<UserPointsReq> userPointsReqList) {for (UserPointsReq userPointsReq : userPointsReqList) {String userId = userPointsReq.getUserId();//先按积分降序,积分相同时按照最后更新时间升序,score = 积分 + (1 - 时间戳/10的13次方)double score = userPointsReq.getPoints() + (1 - userPointsReq.getUpdateTime() / 1e13);this.stringRedisTemplate.opsForZSet().add(redis_key, userId, score);}return true;}/*** 获取用户积分排行榜(倒序)** @param topN 前多少名* @return 前topN的用户积分排名列表*/@GetMapping("/userRankings")public List<UserRanking> userRankings(@RequestParam("topN") int topN) {// 从Redis中获取倒序排列的用户积分数据Set<ZSetOperations.TypedTuple<String>> typedTuples = this.stringRedisTemplate.opsForZSet().reverseRangeWithScores(redis_key, 0, topN - 1);List<UserRanking> userRankingList = new ArrayList<>();for (ZSetOperations.TypedTuple<String> typedTuple : typedTuples) {UserRanking userRanking = new UserRanking();userRanking.setUserId(typedTuple.getValue());userRanking.setRedisScore(typedTuple.getScore());userRankingList.add(userRanking);}return userRankingList;}}

关键字:招聘网站大全_百度推广四川成都地区服务中心_杭州seo网站推广_河南网站定制

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: