springboot+redis實現微博熱搜排行榜的示例代碼
技術模擬思路:
采用26個英文字母來實現排行,隨機為每個字母生成一個隨機數作為score
為瞭更好的體驗,先做幾件事:
- 先初始化1個月的歷史數據
- 定時5秒鐘,模擬微博的熱度刷新(例如模擬點贊 收藏 評論的熱度值更新)
- 定時1小時合並統計 天、周、月的排行榜。
步驟1:先初始化1個月的歷史數據
@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:定時刷新數據
@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:排行榜查詢接口
@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微博熱搜排行榜內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- RedisTemplate常用方法總結
- redis zset實現滑動窗口限流的代碼
- Springboot基礎之RedisUtils工具類
- springboot如何使用redis的incr創建分佈式自增id
- Spring中RedisTemplate的基本使用淺析