✨Feat: 通过定时同步任务将 Redis 数据同步到数据库
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
package cn.hezhaohui.thumb.job;
|
||||
|
||||
import cn.hezhaohui.thumb.mapper.BlogMapper;
|
||||
import cn.hezhaohui.thumb.model.entity.Thumb;
|
||||
import cn.hezhaohui.thumb.model.enums.ThumbTypeEnum;
|
||||
import cn.hezhaohui.thumb.service.ThumbService;
|
||||
import cn.hezhaohui.thumb.util.RedisKeyUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.text.StrPool;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 定时将 Redis 中的临时点赞数据同步到数据库
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class SyncThumb2DBJob {
|
||||
|
||||
@Resource
|
||||
private ThumbService thumbService;
|
||||
|
||||
@Resource
|
||||
private BlogMapper blogMapper;
|
||||
|
||||
@Resource
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
@Scheduled(fixedRate = 10000)
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void run() {
|
||||
log.info("开始执行");
|
||||
DateTime nowDate = DateUtil.date();
|
||||
// 如果秒数为0~9 则回到上一分钟的50秒
|
||||
int second = (DateUtil.second(nowDate) / 10 - 1) * 10;
|
||||
if (second == -10) {
|
||||
second = 50;
|
||||
// 回到上一分钟
|
||||
nowDate = DateUtil.offsetMinute(nowDate, -1);
|
||||
}
|
||||
String date = DateUtil.format(nowDate, "HH:mm:") + second;
|
||||
syncThumb2DBByDate(date);
|
||||
log.info("临时数据同步完成");
|
||||
}
|
||||
|
||||
public void syncThumb2DBByDate(String date) {
|
||||
// 获取到临时点赞和取消点赞数据
|
||||
String tempThumbKey = RedisKeyUtil.getTempThumbKey(date);
|
||||
Map<Object, Object> allTempThumbMap = redisTemplate.opsForHash().entries(tempThumbKey);
|
||||
boolean thumbMapEmpty = CollUtil.isEmpty(allTempThumbMap);
|
||||
|
||||
// 同步 点赞 到数据库
|
||||
// 构建插入列表并收集blogId
|
||||
Map<Long, Long> blogThumbCountMap = new HashMap<>();
|
||||
if (thumbMapEmpty) {
|
||||
return;
|
||||
}
|
||||
ArrayList<Thumb> thumbList = new ArrayList<>();
|
||||
LambdaQueryWrapper<Thumb> wrapper = new LambdaQueryWrapper<>();
|
||||
boolean needRemove = false;
|
||||
for (Object userIdBlogIdObj : allTempThumbMap.keySet()) {
|
||||
String userIdBlogId = (String) userIdBlogIdObj;
|
||||
String[] userIdAndBlogId = userIdBlogId.split(StrPool.COLON);
|
||||
Long userId = Long.valueOf(userIdAndBlogId[0]);
|
||||
Long blogId = Long.valueOf(userIdAndBlogId[1]);
|
||||
// -1 取消点赞,1 点赞
|
||||
Integer thumbType = Integer.valueOf(allTempThumbMap.get(userIdBlogId).toString());
|
||||
if (thumbType == ThumbTypeEnum.INCR.getValue()) {
|
||||
Thumb thumb = new Thumb();
|
||||
thumb.setUserid(userId);
|
||||
thumb.setBlogId(blogId);
|
||||
thumbList.add(thumb);
|
||||
} else if (thumbType == ThumbTypeEnum.DECR.getValue()) {
|
||||
// 拼接查询条件,批量删除
|
||||
needRemove = true;
|
||||
wrapper.or().eq(Thumb::getUserid, userId).eq(Thumb::getBlogId, blogId);
|
||||
} else {
|
||||
if (thumbType != ThumbTypeEnum.NON.getValue()) {
|
||||
log.warn("数据异常:{}", userId + "," + blogId + "," + thumbType);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// 计算点赞增量
|
||||
blogThumbCountMap.put(blogId, blogThumbCountMap.getOrDefault(blogId, 0L) + thumbType);
|
||||
}
|
||||
// 批量插入
|
||||
thumbService.saveBatch(thumbList);
|
||||
// 批量删除
|
||||
if (needRemove) {
|
||||
thumbService.remove(wrapper);
|
||||
}
|
||||
// 批量更新博客点赞量
|
||||
if (!blogThumbCountMap.isEmpty()) {
|
||||
blogMapper.batchUpdateThumbCount(blogThumbCountMap);
|
||||
}
|
||||
// 异步删除
|
||||
Thread.startVirtualThread(() -> {
|
||||
redisTemplate.delete(tempThumbKey);
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user