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.redi