点赞功能设计与实现
时间:2022-07-24
本文章向大家介绍点赞功能设计与实现,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
点赞业务本身并不复杂,无非是对数据的update,但是点赞本身是无意识行为,并且同一个用户可对博文进行点赞/取消点赞,如果直接操作数据库,无疑会增加数据库io操作。
方案:
- 缓存+异步推送
- 缓存+定时任务
优点:
- 降低对数据库的操作
- 提高点赞的效率
缺点:
- redis挂掉,或者mq延迟使数据库数据与redis数据不一致(正在发生) 解决方案:定时同步redis与数据库数据
- 丢失数据 解决方案:MQ挂掉,不解决
数据库设计
CREATE TABLE `user_thumb` (
`like_detail_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '点赞信息ID',
`info_id` bigint(8) DEFAULT NULL COMMENT '图文ID',
`like_create_time` datetime(0) DEFAULT NULL COMMENT '时间',
`like_user_id` bigint(8) DEFAULT NULL COMMENT '点赞人ID',
PRIMARY KEY (`like_detail_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 16 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '点赞记录表' ROW_FORMAT = Dynamic;
实现思路
1.方案一 redis数据结构采用hash或者set都可,前缀自定义,后缀使用图文消息的id
key-value------>{“prefix:图文id” : “用户id”}
2.大key类型拆分
即便是一万用户,频繁操作最大值也是非常大的,对key进行hash取值,
String key = RedisConstants.getLike(infoId%6);
boolean flag = redisService.isMember(key, userId);
3.是否点赞枚举,1:点赞,2:取消点赞
public enum ThumbEnum {
THUMB(1,"点赞"),
CANCELTHUMB(2,"取消点赞"),
private String MessageName;
private Integer type;
public String getType(Integer type) {
return type;
}
public void setMessageName(String messageName) {
MessageName = messageName;
}
ThumbEnum(String messageName) {
MessageName = messageName;
}
}
4.接口实现
根据是否存在key判断是点赞还是取消点赞,所以接口写一个即可
Json thumbOrCancel(Long infoId,Long userId);
impl
String key = RedisConstants.getLike(infoId.toString());
String userIdstr = userId.toString();
//是否已经点过赞
boolean flag = jedisService.isMember(key, userIdstr);
ThumbVo vo = ThumbVo.builder()
.infoId(infoId)
.likeCreateTime(new Date())
.userId(userId)
.build();
Map map = new HashMap();
if (flag) {
//已点过赞则为取消赞操作
redisService.srem(key, userIdStr);
vo.setType(2);//1点赞2取消赞
map.put("isLike", 1);//1未点赞2已点赞
} else {
//记录点赞用户
redisService.sadd(key, userIdStr);
vo.setType(1);
map.put("isLike", 2);
}
//发送消息
userThumbProducer.senduserThumbUp(vo);
resultMap.put("likeCount", redisService.scard(key));
return Json.newInstance(resultMap);
mq
异步去消费调用数据库即可,如果做定时任务去查redis是否有数据,持久化到mysql。
按理说读取与写操作应该分为两个redis,但是点赞统计的是评论数,大key进行拆分后,无需对其读写分离。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 记一次Elasticsearch优化总结
- unix环境高级编程(上)-文件篇
- php webshell下直接反弹shell(不借助任何其他语言)
- XssHtml – 基于白名单的富文本XSS过滤类
- unix环境高级编程(下)-高级IO和进程间通信篇
- mybatis原理,配置介绍及源码分析
- web.py使用不当可能造成代码执行
- 《redis设计与实现》1-数据结构与对象篇
- 《redis设计与实现》2-数据库实现篇
- 利用location来变形我们的XSS Payload
- docker-compose部署单机版本分片mongo
- 一个前端DOMXSS过滤器
- docker-swarm部署mongo分片集群
- lnmp虚拟机安全配置研究
- 遇到一个有趣的逻辑漏洞