您的位置:首页 > 数据库 > Redis

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

2019-01-24 14:27 351 查看

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

目前采用的是可重复计数,就是页面每刷新一次,访问量+1。每次+1都是在 Redis 中加,到每天某个时刻,同步到MySQL数据库中。
一、SpringBoot 定时任务使用
1.在启动类上加 @EnableScheduling 注解

2.创建任务类

package com.liuyanzhao.sens.config;
import com.liuyanzhao.sens.mapper.PostMapper;
import com.liuyanzhao.sens.model.dto.PostViewsDto;
import com.liuyanzhao.sens.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* @author 言曌
* @date 2018/12/24 下午4:55
*/
@Component
@Slf4j
public class ScheduledTasks {
@Autowired
private RedisUtil redisUtil;
@Autowired(required = false)
private PostMapper postMapper;
/**
* 同步文章访问量
*/
@Scheduled(cron = "0 30 4 ? * * ") //每天凌晨4:30执行
public void syncPostViews() {
log.info("======================开始 同步文章访问量======================");
Long startTime = System.nanoTime();
List<PostViewsDto> dtoList = new ArrayList<>();
//从redis取值封装List
Integer prefixLength = "posts_views::posts_views_id_".length();
Set<String> keySet = redisUtil.keys("posts_views::posts_views_id_*");
for (String key : keySet) {
dtoList.add(new PostViewsDto(Long.parseLong(key.substring(prefixLength)), Long.parseLong(redisUtil.get(key))));
}
//更新到数据库中
postMapper.batchUpdatePostViews(dtoList);
Long endTime = System.nanoTime();
log.info("本次文章访问量同步成功, 总耗时: {}", (endTime - startTime) / 1000000 + "ms");
log.info("======================结束 文章访问量结束======================");
}
}

可以写多个方法,每个都需要加 @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属性中拿。

/**
* 修改文章阅读量
* Redis增加,定时器同步
*
* @param postId 文章Id
*/
@Override
public Long updatePostView(Long postId) {
Long view = this.getPostViewsByPostId(postId);
if (view == null) {
return null;
}
return redisUtil.incr("posts_views::posts_views_id_" + postId, 1);
}
/**
* 获得某篇文章的访问量
*
* @return Long
*/
@Override
public Long getPostViewsByPostId(Long postId) {
String str = redisUtil.get("posts_views::posts_views_id_" + postId);
if (str == null) {
Post post = this.findByPostId(postId);
if (post == null) {
return null;
}
redisUtil.set("posts_views::posts_views_id_" + postId, String.valueOf(post.getPostViews()));
return post.getPostViews();
}
return Long.parseLong(str);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: