前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >点赞功能设计与实现

点赞功能设计与实现

作者头像
疯狂的KK
发布2020-08-27 16:14:57
8.6K4
发布2020-08-27 16:14:57
举报
文章被收录于专栏:Java项目实战

点赞业务本身并不复杂,无非是对数据的update,但是点赞本身是无意识行为,并且同一个用户可对博文进行点赞/取消点赞,如果直接操作数据库,无疑会增加数据库io操作。

方案:

  1. 缓存+异步推送
  2. 缓存+定时任务

优点:

  1. 降低对数据库的操作
  2. 提高点赞的效率

缺点:

  1. redis挂掉,或者mq延迟使数据库数据与redis数据不一致(正在发生) 解决方案:定时同步redis与数据库数据
  2. 丢失数据 解决方案:MQ挂掉,不解决

数据库设计

代码语言:javascript
复制
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取值,

代码语言:javascript
复制
String key = RedisConstants.getLike(infoId%6);
boolean flag = redisService.isMember(key, userId);

3.是否点赞枚举,1:点赞,2:取消点赞

代码语言:javascript
复制
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判断是点赞还是取消点赞,所以接口写一个即可

代码语言:javascript
复制
Json thumbOrCancel(Long infoId,Long userId);

impl

代码语言:javascript
复制
       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进行拆分后,无需对其读写分离。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-08-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 赵KK日常技术记录 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档