技术模拟思路:
采用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