技术模拟思路:
采用26个英文字母来实现排行,随机为每个字母生成一个随机数作为score
为了更好的体验,先做几件事:
先初始化1个月的历史数据 定时5秒钟,模拟微博的热度刷新(例如模拟点赞 收藏 评论的热度值更新) 定时1小时合并统计 天、周、月的排行榜。
步骤1:先初始化1个月的历史数据
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
@Service @Slf4j public class InitService {
@Autowired private RedisTemplate redisTemplate;
/** * 先初始化1个月的历史数据 */ public void init30day(){ //计算当前的小时key long hour=System.currentTimeMillis()/( 1000 * 60 * 60 ); //初始化近30天,每天24个key for ( int i= 1 ;i< 24 * 30 ;i++){ //倒推过去30天 String key=Constants.HOUR_KEY+(hour-i); this .initMember(key); System.out.println(key); } }
/** *初始化某个小时的key */ public void initMember(String key) { Random rand = new Random(); //采用26个英文字母来实现排行,随机为每个字母生成一个随机数作为score for ( int i = 1 ;i<= 26 ;i++){ this .redisTemplate.opsForZSet().add(key,String.valueOf(( char )( 96 +i)),rand.nextInt( 10 )); } }
} |
步骤2:定时刷新数据
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
@Service @Slf4j public class TaskService {
@Autowired private RedisTemplate redisTemplate;
/** *2. 定时5秒钟,模拟微博的热度刷新(例如模拟点赞 收藏 评论的热度值更新) * 3. 定时1小时合并统计 天、周、月的排行榜。 */ @PostConstruct public void init(){ log.info( "启动初始化 .........." ); // 2. 定时5秒钟,模拟微博的热度刷新(例如模拟点赞 收藏 评论的热度值更新) new Thread(()-> this .refreshDataHour()).start(); // 3. 定时1小时合并统计 天、周、月的排行榜。 new Thread(()-> this .refreshData()).start(); }
/** *采用26个英文字母来实现排行,随机为每个字母生成一个随机数作为score */ public void refreshHour(){ //计算当前的小时key long hour=System.currentTimeMillis()/( 1000 * 60 * 60 ); //为26个英文字母来实现排行,随机为每个字母生成一个随机数作为score Random rand = new Random(); for ( int i = 1 ;i<= 26 ;i++){ //redis的ZINCRBY 新增这个积分值 this .redisTemplate.opsForZSet().incrementScore(Constants.HOUR_KEY+hour,String.valueOf(( char )( 96 +i)),rand.nextInt( 10 )); } }
/** *刷新当天的统计数据 */ public void refreshDay(){ long hour=System.currentTimeMillis()/( 1000 * 60 * 60 ); List<String> otherKeys= new ArrayList<>(); //算出近24小时内的key for ( int i= 1 ;i< 23 ;i++){ String key=Constants.HOUR_KEY+(hour-i); otherKeys.add(key); } //把当前的时间key,并且把后推23个小时,共计近24小时,求出并集存入Constants.DAY_KEY中 //redis ZUNIONSTORE 求并集 this .redisTemplate.opsForZSet().unionAndStore(Constants.HOUR_KEY+hour,otherKeys,Constants.DAY_KEY);
//设置当天的key 40天过期,不然历史数据浪费内存 for ( int i= 0 ;i< 24 ;i++){ String key=Constants.HOUR_KEY+(hour-i); this .redisTemplate.expire(key, 40 , TimeUnit.DAYS); } log.info( "天刷新完成.........." ); } /** *刷新7天的统计数据 */ public void refreshWeek(){ long hour=System.currentTimeMillis()/( 1000 * 60 * 60 ); List<String> otherKeys= new ArrayList<>(); //算出近7天内的key for ( int i= 1 ;i< 24 * 7 - 1 ;i++){ String key=Constants.HOUR_KEY+(hour-i); otherKeys.add(key); } //把当前的时间key,并且把后推24*7-1个小时,共计近24*7小时,求出并集存入Constants.WEEK_KEY中 this .redisTemplate.opsForZSet().unionAndStore(Constants.HOUR_KEY+hour,otherKeys,Constants.WEEK_KEY);
log.info( "周刷新完成.........." ); }
/** *刷新30天的统计数据 */ public void refreshMonth(){ long hour=System.currentTimeMillis()/( 1000 * 60 * 60 ); List<String> otherKeys= new ArrayList<>(); //算出近30天内的key for ( int i= 1 ;i< 24 * 30 - 1 ;i++){ String key=Constants.HOUR_KEY+(hour-i); otherKeys.add(key); } //把当前的时间key,并且把后推24*30个小时,共计近24*30小时,求出并集存入Constants.MONTH_KEY中 this .redisTemplate.opsForZSet().unionAndStore(Constants.HOUR_KEY+hour,otherKeys,Constants.MONTH_KEY); log.info( "月刷新完成.........." ); }
/** *定时1小时合并统计 天、周、月的排行榜。 */ public void refreshData(){ while ( true ){ //刷新当天的统计数据 this .refreshDay(); // 刷新7天的统计数据 this .refreshWeek(); // 刷新30天的统计数据 this .refreshMonth(); //TODO 在分布式系统中,建议用xxljob来实现定时 try { Thread.sleep( 1000 * 60 * 60 ); } catch (InterruptedException e) { e.printStackTrace(); } } }
/** *定时5秒钟,模拟微博的热度刷新(例如模拟点赞 收藏 评论的热度值更新) */ public void refreshDataHour(){ while ( true ){ this .refreshHour(); //TODO 在分布式系统中,建议用xxljob来实现定时 try { Thread.sleep( 5000 ); } catch (InterruptedException e) { e.printStackTrace(); } } } } |
步骤3:排行榜查询接口
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
@RestController @Slf4j public class Controller {
@Autowired private RedisTemplate redisTemplate;
@GetMapping (value = "/getHour" ) public Set getHour() { long hour=System.currentTimeMillis()/( 1000 * 60 * 60 ); //ZREVRANGE 返回有序集key中,指定区间内的成员,降序。 Set<ZSetOperations.TypedTuple<Integer>> rang= this .redisTemplate.opsForZSet().reverseRangeWithScores(Constants.HOUR_KEY+hour, 0 , 30 ); return rang; } @GetMapping (value = "/getDay" ) public Set getDay() { Set<ZSetOperations.TypedTuple<Integer>> rang= this .redisTemplate.opsForZSet().reverseRangeWithScores(Constants.DAY_KEY, 0 , 30 ); return rang; }
@GetMapping (value = "/getWeek" ) public Set getWeek() { Set<ZSetOperations.TypedTuple<Integer>> rang= this .redisTemplate.opsForZSet().reverseRangeWithScores(Constants.WEEK_KEY, 0 , 30 ); return rang; }
@GetMapping (value = "/getMonth" ) public Set getMonth() { Set<ZSetOperations.TypedTuple<Integer>> rang= this .redisTemplate.opsForZSet().reverseRangeWithScores(Constants.MONTH_KEY, 0 , 30 ); return rang; } } |
到此这篇关于springboot+redis实现微博热搜排行榜的示例代码的文章就介绍到这了,更多相关springboot redis微博热搜排行榜内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
原文链接:https://blog.csdn.net/INGNIGHT/article/details/106941747
查看更多关于springboot+redis实现微博热搜排行榜的示例代码的详细内容...