0.前言
本文基于Springboot利用Redis實作點贊功能的緩存和定時持久化接口。
使用者對浏覽内容進行【點贊/取贊】,并發送【點贊/取贊】請求到後端,這些資訊先存入Redis中緩存,再每隔兩小時将Redis中的内容直接寫入資料庫持久化存儲。
1.項目目錄結構
2.Redis緩存點贊消息
1.設計思路
使用者點贊一條資料,設定狀态為0,并且更新被點贊内容的likeCount+1
使用者取消點贊一條資料,設定狀态為1,并且更新被點贊内容的likeCount+0
1.1 Redis鍵值對設計
選用Hash(散列)存儲
點贊資訊
- key: (String) 浏覽資訊id和點贊使用者id拼接而成, 分隔符為::
- value: (HashMap) 存儲點贊狀态(0: 點贊 1:取消點贊)和更新時間的時間戳
- key: "浏覽資訊id::點贊使用者id" value: {status: Integer, updateTime: long}
點贊數量
- key: (String) 浏覽資訊id
- value: (Integer) 點贊數量
1.2 點贊
- 使用者點贊資訊,發送點贊請求到後端
- 後端判斷該點贊資訊在Redis中的狀态
- Redis不進行存儲,并提醒前端重複存儲。
- 更新/新增點贊資訊
- 更新/新增點贊量
- 【不存在(沒有對應key) 】|| 【取消點贊(即取出的status為1)】
- 【點贊(即取出的status為0,此時相當于重複點贊行為)】
- 一次點贊請求完畢
1.3 取消點贊
- 使用者取消點贊資訊,發送取消點贊請求到後端
- 後端判斷該點贊資訊在Redis中的狀态
- 更新/新增點贊資訊
- 更新/新增點贊量
- Redis不進行存儲,并提醒前端重複存儲。
- 更新/新增點贊資訊
- 增加0條内容點贊量
- 【不存在(沒有對應key) 】
- 【取消點贊(即取出的status為1,此時相當于重複取消點贊行為)】
- 【點贊(即取出的status為0)】
- 一次取消點贊請求完畢
2.核心代碼實作
2.1 Redis封裝
具體實作參考該部落格,不在贅述。
https://www.cnblogs.com/caizhaokai/p/11037610.html
2.2 工具類
1.時間戳轉化為LocalDateTime
import java.time.Instant;import java.time.LocalDateTime;import java.time.ZoneId;/** * 工具類:将時間戳轉化為LocalDateTime * 主要是因為redis不好存儲LocalDateTime,存儲timestamp友善一點,而且格式可以随意改變 */public class LocalDateTimeConvertUtil { public static LocalDateTime getDateTimeOfTimestamp(long timestamp) { Instant instant = Instant.ofEpochMilli(timestamp); ZoneId zone = ZoneId.systemDefault(); return LocalDateTime.ofInstant(instant, zone); }}
2.RedisKey處理類
public class RedisKeyUtils { /** * 儲存使用者點贊内容資料的key * @date 2021/9/26 14:44 */ public static final String MAP_KEY_USER_LIKED = "MAP_USER_LIKED"; /** * 儲存内容被點贊數量的key * @date 2021/9/26 14:44 */ public static final String MAP_KEY_USER_LIKED_COUNT = "MAP_USER_LIKED_COUNT"; /** * 拼接被點贊的内容id和點贊的人的id作為key。格式 222222::333333 * @param infoId 被點贊的内容 id * @param likeUserId 點贊的人的id * @return */ public static String getLikedKey(String infoId, String likeUserId){ return infoId + "::" + likeUserId; }}
2.3 DTO
// UserLikesDTO.java@Data@AllArgsConstructor@NoArgsConstructorpublic class UserLikesDTO { private String infoId; private String likeUserId; private Integer status; private LocalDateTime updateTime;}// UserLikeCountDTO.java@Data@AllArgsConstructor@NoArgsConstructorpublic class UserLikeCountDTO { private String infoId; private Integer likeCount;}
2.4 Service
- interface
// RedisService.javaimport com.csu.edu.redisLikeDemo.domain.DTO.UserLikeCountDTO;import com.csu.edu.redisLikeDemo.domain.DTO.UserLikesDTO;import java.util.List;/** * 負責将資料寫入Redis緩存 */public interface RedisService { /** * 擷取點贊狀态 * @param infoId * @param likeUserId */ Integer getLikeStatus(String infoId, String likeUserId); /** * 點贊。狀态為1 * @param infoId * @param likeUserId */ void saveLiked2Redis(String infoId, String likeUserId); /** * 取消點贊。将狀态改變為0 * @param infoId * @param likeUserId */ void unlikeFromRedis(String infoId, String likeUserId); /** * 從Redis中删除一條點贊資料 * @param infoId * @param likeUserId */ void deleteLikedFromRedis(String infoId, String likeUserId); /** * 該内容的點贊數變化Δdelta * @param infoId */ void in_decrementLikedCount(String infoId, Integer delta); /** * 擷取Redis中存儲的所有點贊資料 * @return */ List<UserLikesDTO> getLikedDataFromRedis(); /** * 擷取Redis中存儲的所有點贊數量 * @return */ List<UserLikeCountDTO> getLikedCountFromRedis();}
- implement
import com.csu.edu.redisLikeDemo.common.CONSTANT;import com.csu.edu.redisLikeDemo.domain.DTO.UserLikeCountDTO;import com.csu.edu.redisLikeDemo.domain.DTO.UserLikesDTO;import com.csu.edu.redisLikeDemo.service.RedisService;import com.csu.edu.redisLikeDemo.util.LocalDateTimeConvertUtil;import com.csu.edu.redisLikeDemo.util.RedisKeyUtils;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.Cursor;import org.springframework.data.redis.core.HashOperations;import org.springframework.data.redis.core.ScanOptions;import org.springframework.stereotype.Service;import java.time.LocalDateTime;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;@Service("redisService")@Slf4jpublic class RedisServiceImpl implements RedisService { @Autowired private HashOperations<String, String, Object> redisHash;// Redis Hash @Override public Integer getLikeStatus(String infoId, String likeUserId) { if (redisHash.hasKey(RedisKeyUtils.MAP_KEY_USER_LIKED, RedisKeyUtils.getLikedKey(infoId, likeUserId))){ HashMap<String, Object> map = (HashMap<String, Object>) redisHash.get(RedisKeyUtils.MAP_KEY_USER_LIKED, RedisKeyUtils.getLikedKey(infoId, likeUserId)); return (Integer) map.get("status"); } return CONSTANT.LikedStatusEum.NOT_EXIST.getCode(); } @Override public void saveLiked2Redis(String infoId, String likeUserId) { // 生成key String key = RedisKeyUtils.getLikedKey(infoId, likeUserId); // 封裝value 喜歡狀态 更新時間 HashMap<String,Object> map = new HashMap<>(); map.put("status",CONSTANT.LikedStatusEum.LIKE.getCode()); map.put("updateTime", System.currentTimeMillis()); redisHash.put(RedisKeyUtils.MAP_KEY_USER_LIKED, key, map); } @Override public void unlikeFromRedis(String infoId, String likeUserId) { // 生成key String key = RedisKeyUtils.getLikedKey(infoId, likeUserId); // 封裝value 喜歡狀态 更新時間 HashMap<String,Object> map = new HashMap<>(); map.put("status",CONSTANT.LikedStatusEum.UNLIKE.getCode()); map.put("updateTime", System.currentTimeMillis());// 存入目前時間戳 redisHash.put(RedisKeyUtils.MAP_KEY_USER_LIKED, key, map); } @Override public void deleteLikedFromRedis(String infoId, String likeUserId) { String key = RedisKeyUtils.getLikedKey(infoId, likeUserId); redisHash.delete(RedisKeyUtils.MAP_KEY_USER_LIKED, key); } @Override public void in_decrementLikedCount(String infoId, Integer delta) { redisHash.increment(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, infoId, delta); } @Override public List<UserLikesDTO> getLikedDataFromRedis() { // scan 讀取資料,比key比對優雅 Cursor<Map.Entry<String, Object>> cursor = redisHash.scan(RedisKeyUtils.MAP_KEY_USER_LIKED, ScanOptions.NONE); List<UserLikesDTO> list = new ArrayList<>(); while (cursor.hasNext()){ Map.Entry<String, Object> entry = cursor.next(); String key = (String) entry.getKey(); //分離出 infoId,likedPostId, 解析value String[] split = key.split("::"); String infoId = split[0]; String likeUserId = split[1]; HashMap<String, Object> map = (HashMap<String, Object>) entry.getValue(); Integer status = (Integer) map.get("status"); long updateTimeStamp = (long) map.get("updateTime"); LocalDateTime updateTime = LocalDateTimeConvertUtil.getDateTimeOfTimestamp(updateTimeStamp);// 時間戳轉為LocalDateTime //組裝成 UserLike 對象 UserLikesDTO userLikesDTO = new UserLikesDTO(infoId, likeUserId, status, updateTime); list.add(userLikesDTO); //存到 list 後從 Redis 中清理緩存 redisHash.delete(RedisKeyUtils.MAP_KEY_USER_LIKED, key); } return list; } @Override public List<UserLikeCountDTO> getLikedCountFromRedis() { // scan 讀取資料,比key比對優雅 Cursor<Map.Entry<String, Object>> cursor = redisHash.scan(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, ScanOptions.NONE); List<UserLikeCountDTO> list = new ArrayList<>(); while (cursor.hasNext()){ Map.Entry<String, Object> map = cursor.next(); //将點贊數量存儲在 LikedCountDT String key = (String)map.getKey(); UserLikeCountDTO dto = new UserLikeCountDTO(key, (Integer) map.getValue()); list.add(dto); //從Redis中删除這條記錄 redisHash.delete(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, key); } return list; }}
2.5 controller & API
- controller
import com.csu.edu.redisLikeDemo.common.CommonResponse;import com.csu.edu.redisLikeDemo.service.LikeService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController@RequestMapping("/test/")public class LikeController { @Autowired private LikeService likeService; @PostMapping("like") public CommonResponse<Object> likeInfo( String infoId, String userId){ return likeService.likeInfo(infoId, userId); } @PostMapping("dislike") public CommonResponse<Object> dislikeInfo( String infoId, String userId){ return likeService.dislikeInfo(infoId, userId); }}
- 接口測試
牛逼啊!接私活必備的 N 個開源項目!趕快收藏
3.Redis定時持久化
1.設計思路
1.1 資料庫設計
# 浏覽内容表DROP TABLE IF EXISTS `view_item`;CREATE TABLE `view_item` ( `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '内容id(如文章、短視訊等等)', `create_user` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '建立者', `like_count` int(11) NULL DEFAULT NULL COMMENT '點贊數', `cmt_count` int(11) NULL DEFAULT NULL COMMENT '評論數', `share_count` int(11) NULL DEFAULT NULL COMMENT '分享數', `create_time` datetime(0) NULL DEFAULT NULL COMMENT '建立時間', `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新時間', PRIMARY KEY (`id`) USING BTREE) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;SET FOREIGN_KEY_CHECKS = 1;# 點贊-使用者表DROP TABLE IF EXISTS `user_likes`;CREATE TABLE `user_likes` ( `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '點贊資訊ID', `info_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '點贊對象id', `like_user_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '點贊人ID', `status` tinyint(4) NULL DEFAULT 0 COMMENT '0 點贊 1 取消 ', `create_time` datetime(0) NULL DEFAULT NULL COMMENT '建立時間', `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新時間', PRIMARY KEY (`id`) USING BTREE, UNIQUE INDEX `agdkey`(`like_user_id`, `info_id`) USING BTREE) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '點贊記錄表' ROW_FORMAT = Dynamic;
1.2 流程
- 周遊Redis的【點贊資訊】,僅改變資料庫中點贊資訊的狀态
- 判斷目前點贊資訊是否在資料庫中
- 否,則更新資料
- 資料庫中新增點贊-使用者記錄
- 更新内容的點贊量
- 轉到6
- 是
- 轉到第3步
- 判斷資料庫中的點贊狀态與緩存中的點贊狀态(status)
- 一緻
- 狀态不改變
- 點贊數量-1(兩種情況邏輯分析有差異,但是最終結果均為-1)
- 結束
- 不一緻,則需要針對具體情況改變
- 轉到步驟4
- 判斷資料庫點贊狀态
- 已經點贊,需要更改為取消點贊
- 資料庫中修改為取消點贊狀态
- 更新緩存中的點贊數量-1(減去資料庫中持久化的一個點贊量,一會兒緩存會和資料庫點贊總量加和)
- 取消點贊,需要更改
- 資料庫中修改為點贊狀态
- 無需更新緩存中的點贊數量,因為緩存中已經+1(即該點贊資料的點贊量)
- 将緩存【點贊數量】持久化并清理緩存 此處修改資料庫中的點贊數量
- 完成緩存持久化
1.3定時寫入
使用 Quartz redis 定時任務持久化存儲到資料庫
<!-- Quartz redis定時任務持久化存儲到資料庫 --><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-quartz</artifactId></dependency>
2.核心代碼實作
2.1Bean
import com.baomidou.mybatisplus.annotation.TableField;import com.baomidou.mybatisplus.annotation.TableId;import com.baomidou.mybatisplus.annotation.TableName;import lombok.Data;import java.time.LocalDateTime;@Data@TableName("user_likes")public class UserLikes { @TableId private String id; @TableField("info_id") private String infoId; @TableField("like_user_id") private String likeUserId; private Integer status; @TableField("create_time") private LocalDateTime createTime; @TableField("update_time") private LocalDateTime updateTime;}
import com.baomidou.mybatisplus.annotation.TableField;import com.baomidou.mybatisplus.annotation.TableId;import com.baomidou.mybatisplus.annotation.TableName;import lombok.Data;import java.time.LocalDateTime;@Data@TableName("view_item")public class ViewItem { @TableId private String id; @TableField("create_user") private String createUser; @TableField("like_count") private Integer likeCount; @TableField("cmt_count") private Integer cmtCount; @TableField("share_count") private Integer shareCount; @TableField("create_time") private LocalDateTime createTime; @TableField("update_time") private LocalDateTime updateTime;}
2.2 Service
- interface
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.csu.edu.redisLikeDemo.domain.UserLikes;/** * 負責将Redis緩存中的資料持久化到資料庫中 */public interface DBService { /** * 儲存點贊記錄 * @param userLike * @return */ Boolean save(UserLikes userLike); /** * 更新點贊記錄 * @param userLike * @return */ Boolean update(UserLikes userLike); /** * 根據内容的id查詢點贊清單(即查詢都誰給這個内容點贊過) * @param infoId 内容的id * @return */ Page<UserLikes> getLikedListByInfoId(String infoId, int pageNum, int pageSize); /** * 根據點贊人的id查詢點贊清單(即查詢這個人都給哪些内容點贊過) * @param likeUserId * @return */ Page<UserLikes> getLikedListByLikeUserId(String likeUserId, int pageNum, int pageSize); /** * 通過被點贊内容和點贊人id查詢是否存在點贊記錄 * @param infoId * @param likeUserId * @return */ UserLikes getByInfoIdAndLikeUserId(String infoId, String likeUserId); /** * 将Redis裡的點贊資料存入資料庫中,True 表示還需要進一步持久化, False表示資料庫中已存在該資料,無需進一步持久化 */ void transLikedFromRedis2DB(); /** * 将Redis中的點贊數量資料存入資料庫 */ void transLikedCountFromRedis2DB();}
- implement
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.csu.edu.redisLikeDemo.common.CONSTANT;import com.csu.edu.redisLikeDemo.domain.DTO.UserLikeCountDTO;import com.csu.edu.redisLikeDemo.domain.DTO.UserLikesDTO;import com.csu.edu.redisLikeDemo.domain.UserLikes;import com.csu.edu.redisLikeDemo.domain.ViewItem;import com.csu.edu.redisLikeDemo.mapper.UserLikesMapper;import com.csu.edu.redisLikeDemo.mapper.ViewItemMapper;import com.csu.edu.redisLikeDemo.service.DBService;import com.csu.edu.redisLikeDemo.service.RedisService;import lombok.extern.slf4j.Slf4j;import org.apache.commons.collections4.CollectionUtils;import org.n3r.idworker.Sid;import org.springframework.beans.BeanUtils;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.time.LocalDateTime;import java.util.HashMap;import java.util.List;@Service("dbService")@Slf4jpublic class DBServiceImpl implements DBService { @Autowired private RedisService redisService; @Autowired private UserLikesMapper userLikesMapper; @Autowired private ViewItemMapper viewItemMapper; @Autowired private Sid sid;// Id生成器,利用idWorker産生唯一(不重複)自增式的id,可以根據需求選用其他方式,比如MyBatisPlus的自增 @Override public Boolean save(UserLikes userLike) { int rows = userLikesMapper.insert(userLike); return rows > 0; } @Override public Boolean update(UserLikes userLike) { UpdateWrapper<UserLikes> updateWrapper = new UpdateWrapper<>(); updateWrapper.set("status", userLike.getStatus()); updateWrapper.set("update_time",userLike.getUpdateTime()); updateWrapper.eq("id",userLike.getId()); int rows = userLikesMapper.update(userLike,updateWrapper); return rows > 0; } @Override public Page<UserLikes> getLikedListByInfoId(String infoId, int pageNum, int pageSize) { // 分頁擷取喜歡清單資訊 Page<UserLikes> result = new Page<>(); result.setCurrent(pageNum); result.setSize(pageSize); // 擷取内容的id查詢點贊清單 QueryWrapper<UserLikes> queryWrapper = new QueryWrapper(); queryWrapper.eq("info_id",infoId); result = userLikesMapper.selectPage(result, queryWrapper); log.info("獲得内容的id查詢點贊清單(即查詢都有誰給這個内容點贊過)"); return result; } @Override public Page<UserLikes> getLikedListByLikeUserId (String likeUserId, int pageNum, int pageSize) { // 分頁擷取喜歡清單資訊 Page<UserLikes> result = new Page<>(); result.setCurrent(pageNum); result.setSize(pageSize); // 擷取使用者的id查詢點贊清單 QueryWrapper<UserLikes> queryWrapper = new QueryWrapper(); queryWrapper.eq("like_user_id", likeUserId); result = userLikesMapper.selectPage(result, queryWrapper); log.info("擷取點贊人的id查詢點贊清單(即查詢這個人都給哪些内容點贊過)"); return result; } @Override public UserLikes getByInfoIdAndLikeUserId (String infoId, String likeUserId) { HashMap<String, Object> map = new HashMap<>(); map.put("info_id",infoId); map.put("like_user_id",likeUserId); try{ UserLikes userLikes = userLikesMapper.selectByMap(map).get(0); log.info("通過被點贊人和點贊人id查詢是否存在點贊記錄"); return userLikes; }catch (Exception e){ log.info("目前查詢的被點贊人和點贊人id不存在點贊記錄"); return null; } } @Override public void transLikedFromRedis2DB() { // 批量擷取緩存中的點贊資料 List<UserLikesDTO> list = redisService.getLikedDataFromRedis(); if (CollectionUtils.isEmpty(list))// 為空,不寫入 return; for (UserLikesDTO item: list){ UserLikes userLikes = getByInfoIdAndLikeUserId(item.getInfoId(), item.getLikeUserId());// 在資料庫中查詢 if (userLikes == null) {// 無記錄,新增 if(!save(userLikesDTOtoUserLikes(item))){ log.info("新增點贊資料失敗!"); return; // System.out.println("緩存記錄寫入資料庫失敗!請重試"); } }else {// 有記錄,更新 // 判斷資料庫中點贊狀态與緩存中點贊狀态一緻性 if (userLikes.getStatus()==item.getStatus()){// 一緻,無需持久化,點贊數量-1 redisService.in_decrementLikedCount(item.getInfoId(), -1); }else{// 不一緻 if (userLikes.getStatus()== CONSTANT.LikedStatusEum.LIKE.getCode()){// 在資料庫中已經是點贊,則取消點贊,同時記得redis中的count-1 // 之前是點贊,現在改為取消點贊 1.設定更改status 2. redis中的count要-1(消除在資料庫中自己的記錄) userLikes.setStatus(CONSTANT.LikedStatusEum.UNLIKE.getCode()); redisService.in_decrementLikedCount(item.getInfoId(), -1); } else if (userLikes.getStatus()== CONSTANT.LikedStatusEum.UNLIKE.getCode()) {// 未點贊,則點贊,修改點贊狀态和點贊資料+1 userLikes.setStatus(CONSTANT.LikedStatusEum.LIKE.getCode()); redisService.in_decrementLikedCount(item.getInfoId(), 1); } userLikes.setUpdateTime(LocalDateTime.now()); if(!update(userLikes)){// 更新點贊資料 log.info("更新點贊資料失敗!"); return; // System.out.println("緩存記錄更新資料庫失敗!請重試"); } } } } } @Override public void transLikedCountFromRedis2DB() {// 擷取緩存中内容的點贊數清單 List<UserLikeCountDTO> list = redisService.getLikedCountFromRedis(); if (CollectionUtils.isEmpty(list))// 為空,不寫入 return; for (UserLikeCountDTO item: list){ ViewItem viewItem = viewItemMapper.selectById(item.getInfoId()); if (viewItem != null) {// 新增點贊數 Integer likeCount = viewItem.getLikeCount() + item.getLikeCount(); System.out.println("内容id不為空,更新内容點贊數量"); viewItem.setLikeCount(likeCount); UpdateWrapper<ViewItem> updateWrapper = new UpdateWrapper<>(); updateWrapper.set("like_count", viewItem.getLikeCount()); updateWrapper.eq("id", viewItem.getId()); int rows = viewItemMapper.update(viewItem, updateWrapper); if (rows > 0) { System.out.println("成功更新内容點贊數!"); return; } } System.out.println("内容id不存在,無法将緩存資料持久化!"); } } private UserLikes userLikesDTOtoUserLikes(UserLikesDTO userLikesDTO){ UserLikes userLikes = new UserLikes(); userLikes.setId(sid.nextShort()); BeanUtils.copyProperties(userLikesDTO,userLikes); userLikes.setCreateTime(LocalDateTime.now()); userLikes.setUpdateTime(LocalDateTime.now()); return userLikes; }}
3. 定時更新資料庫
3.1 定時任務
import com.csu.edu.redisLikeDemo.service.DBService; import lombok.extern.slf4j.Slf4j;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.scheduling.quartz.QuartzJobBean;import java.text.SimpleDateFormat;import java.util.Date;/** * 定時任務 */@Slf4jpublic class CronUtil extends QuartzJobBean { @Autowired private DBService dbService; private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); /** * 執行的定時任務 */ @Override protected void executeInternal(JobExecutionContext context) throws JobExecutionException { log.info("LikeTask-------- {}", sdf.format(new Date())); //将 Redis 裡的點贊資訊同步到資料庫裡 dbService.transLikedFromRedis2DB(); dbService.transLikedCountFromRedis2DB(); }}
3.2 定時任務配置
設定每兩個小時更新一次資料庫
import com.csu.edu.redisLikeDemo.util.CronUtil;import org.quartz.*;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/** * 開啟定時任務持久化存儲到資料庫 */@Configurationpublic class QuartzConfig { private static final String LIKE_TASK_IDENTITY = "LikeTaskQuartz"; @Bean public JobDetail quartzDetail(){ return JobBuilder.newJob(CronUtil.class).withIdentity(LIKE_TASK_IDENTITY).storeDurably().build(); } @Bean public Trigger quartzTrigger(){ SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()// .withIntervalInSeconds(20) //設定時間周期機關秒 .withIntervalInHours(2) //兩個小時執行一次 .repeatForever(); return TriggerBuilder.newTrigger().forJob(quartzDetail()) .withIdentity(LIKE_TASK_IDENTITY) .withSchedule(scheduleBuilder) .build(); }}
4.項目源碼位址 & 參考
項目源碼:
https://github.com/WuYiheng-Og/redislike
原文連結:https://mp.weixin.qq.com/s/qSM0SE2XI7ZsUCFHEr4IaQ