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 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 allTempThumbMap = redisTemplate.opsForHash().entries(tempThumbKey); boolean thumbMapEmpty = CollUtil.isEmpty(allTempThumbMap); // 同步 点赞 到数据库 // 构建插入列表并收集blogId Map blogThumbCountMap = new HashMap<>(); if (thumbMapEmpty) { return; } ArrayList thumbList = new ArrayList<>(); LambdaQueryWrapper 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); }); } }