SpringBoot 定时任务从Redis同步文章访问量

在新开发的博客系统中,引入了大量redis,文章/文章列表/分类/标签/评论等等都先从MySQL读取,之后都是从Redis读取。而文章访问量应该怎么设计呢?,每刷新一次+1,数据库异步+1吗?还是使用cookie记录访问了哪些文章,再次刷新不重复计数?

目前采用的是可重复计数,就是页面每刷新一次,访问量+1。每次+1都是在 Redis 中加,到每天某个时刻,同步到MySQL数据库中。

 

一、SpringBoot 定时任务使用

1.在启动类上加 @EnableScheduling 注解

SpringBoot 定时任务从Redis同步文章访问量

 

2.创建任务类

  1. package com.liuyanzhao.sens.config;
  2. import com.liuyanzhao.sens.mapper.PostMapper;
  3. import com.liuyanzhao.sens.model.dto.PostViewsDto;
  4. import com.liuyanzhao.sens.utils.RedisUtil;
  5. import lombok.extern.slf4j.Slf4j;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.scheduling.annotation.Scheduled;
  8. import org.springframework.stereotype.Component;
  9. import java.util.ArrayList;
  10. import java.util.List;
  11. import java.util.Set;
  12. /**
  13.  * @author 言曌
  14.  * @date 2018/12/24 下午4:55
  15.  */
  16. @Component
  17. @Slf4j
  18. public class ScheduledTasks {
  19.     @Autowired
  20.     private RedisUtil redisUtil;
  21.     @Autowired(required = false)
  22.     private PostMapper postMapper;
  23.     /**
  24.      * 同步文章访问量
  25.      */
  26.     @Scheduled(cron = "0 30 4 ? * * "//每天凌晨4:30执行
  27.     public void syncPostViews() {
  28.         log.info("======================开始 同步文章访问量======================");
  29.         Long startTime = System.nanoTime();
  30.         List<PostViewsDto> dtoList = new ArrayList<>();
  31.         //从redis取值封装List
  32.         Integer prefixLength = "posts_views::posts_views_id_".length();
  33.         Set<String> keySet = redisUtil.keys("posts_views::posts_views_id_*");
  34.         for (String key : keySet) {
  35.             dtoList.add(new PostViewsDto(Long.parseLong(key.substring(prefixLength)), Long.parseLong(redisUtil.get(key))));
  36.         }
  37.         //更新到数据库中
  38.         postMapper.batchUpdatePostViews(dtoList);
  39.         Long endTime = System.nanoTime();
  40.         log.info("本次文章访问量同步成功, 总耗时: {}", (endTime - startTime) / 1000000 + "ms");
  41.         log.info("======================结束 文章访问量结束======================");
  42.     }
  43. }

可以写多个方法,每个都需要加 @Scheduled 注解,指定相应时间就行。

下面给出一些常用的时间格式

"0 0 12 * * ?"    每天中午十二点触发

"0 15 10 ? * *"    每天早上10:15触发

"0 15 10 * * ?"    每天早上10:15触发

"0 15 10 * * ? *"    每天早上10:15触发

"0 15 10 * * ? 2005"    2005年的每天早上10:15触发

"0 * 14 * * ?"    每天从下午2点开始到2点59分每分钟一次触发

"0 0/5 14 * * ?"    每天从下午2点开始到2:55分结束每5分钟一次触发

"0 0/5 14,18 * * ?"    每天的下午2点至2:55和6点至6点55分两个时间段内每5分钟一次触发

"0 0-5 14 * * ?"    每天14:00至14:05每分钟一次触发

"0 10,44 14 ? 3 WED"    三月的每周三的14:10和14:44触发

"0 15 10 ? * MON-FRI"    每个周一、周二、周三、周四、周五的10:15触发

 

二、文章访问量的设计

文章表里一个 post_views 字段,即文章访问量。

当查看文章详情的时候,查询一下该文章的访问量,通常是从缓存中拿,如果没有,从文章对象的postViews属性中拿。

  1. /**
  2.      * 修改文章阅读量
  3.      * Redis增加,定时器同步
  4.      *
  5.      * @param postId 文章Id
  6.      */
  7.     @Override
  8.     public Long updatePostView(Long postId) {
  9.         Long view = this.getPostViewsByPostId(postId);
  10.         if (view == null) {
  11.             return null;
  12.         }
  13.         return redisUtil.incr("posts_views::posts_views_id_" + postId, 1);
  14.     }
  15.     /**
  16.      * 获得某篇文章的访问量
  17.      *
  18.      * @return Long
  19.      */
  20.     @Override
  21.     public Long getPostViewsByPostId(Long postId) {
  22.         String str = redisUtil.get("posts_views::posts_views_id_" + postId);
  23.         if (str == null) {
  24.             Post post = this.findByPostId(postId);
  25.             if (post == null) {
  26.                 return null;
  27.             }
  28.             redisUtil.set("posts_views::posts_views_id_" + postId, String.valueOf(post.getPostViews()));
  29.             return post.getPostViews();
  30.         }
  31.         return Long.parseLong(str);
  32.     }

 

 

  • 微信
  • 交流学习,有偿服务
  • weinxin
  • 博客/Java交流群
  • 资源分享,问题解决,技术交流。群号:590480292
  • weinxin
言曌

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: