点赞功能设计与实现

举报
赵KK日常技术记录 发表于 2023/06/29 22:55:31 2023/06/29
【摘要】 点赞业务本身并不复杂,无非是对数据的update,但是点赞本身是无意识行为,并且同一个用户可对博文进行点赞/取消点赞,如果直接操作数据库,无疑会增加数据库io操作。方案:缓存+异步推送缓存+定时任务优点:降低对数据库的操作提高点赞的效率缺点:redis挂掉,或者mq延迟使数据库数据与redis数据不一致(正在发生)解决方案:定时同步redis与数据库数据丢失数据解决方案:MQ挂掉,不解决图片...

点赞业务本身并不复杂,无非是对数据的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进行拆分后,无需对其读写分离。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。