Redis achieve functional modules thumbs up

Before reading an article, speak redis scenarios, one scenario is to achieve thumbs up function, paper come fear felt shallow, we must combat a wave

Function Point Design

For example, I like to send the article on the site of Denver features a little praise, praise of the total number of statistics point article, a few points like all the articles of the user, so the design of thumbs up function module has the following functions:

  • Like the number of points of an article
  • Like all the users point of the article number
  • Users thumbs article
  • Persisted to the MySQLdatabase

Database Design

  • Redis database design Redisis K-Vthe database, there is no uniform data structure, designed for different functions with different points of K-Vstorage structure

    • Like several points of an article using the user HashMapdata structure HashMapis keyas articleId, valueas Set, Setthe value of the user ID, i.e.,HashMap<String, Set<String>>
    • Like the total number of points the user to use HashMapthe data structure, HashMapthe keyis userId, valueto Stringrecord the total number of thumbs
    • Like the user point of use of the article in HashMapa data structure, HashMapthe keyis userId, valueas Set, Setin the value of the article ID, i.e.,HashMap<String, Set<String>>
  • MySQL database design, the most important two tables, articletables anduser_like_article

    • articleTable Structure
    Field Values Field Type Explanation
    article_name varchar Article name
    content blob Article Content
    total_like_count bigint The total number of articles thumbs up

    Articles total number of points need to praise and Redisto synchronize the number of points Chan

    • user_like_articleTable Structure
    Field Values Field Type Explanation
    user_id bigint User ID
    article_id bigint Article ID

    Record user information thumbs up article, is an intermediate table

Description: Table design is omitted id, deleted, gmt_create, gmt_modifiedfield

flow chart

Flowchart is relatively simple, and the cancel point Like steps to achieve substantially the same point Like

  • Parameter check incoming parameter nullvalue determination
  • Like the user check logic point, the user can repeat the same point Like for the cancellation of the article thumbs, the user can not cancel the article points Like
  • Deposited Redisinto the data there are a few points like all the articles, like the number of point, the user point of an article like this article
  • Timing object is achieved by a timing of execution [1 hour], the Redisread data into the persistence MySQLof

Code function realization

  • like
public void likeArticle(Long articleId, Long likedUserId, Long likedPostId) {
    validateParam(articleId, likedUserId, likedPostId);  //参数验证

    logger.info("点赞数据存入redis开始,articleId:{},likedUserId:{},likedPostId:{}", articleId, likedUserId, likedPostId);
    synchronized (this) {
        //只有未点赞的用户才可以进行点赞
        likeArticleLogicValidate(articleId, likedUserId, likedPostId);
        //1.用户总点赞数+1
        redisTemplate.opsForHash().increment(TOTAL_LIKE_COUNT_KEY, String.valueOf(likedUserId), 1);

        //2.用户喜欢的文章+1
        String userLikeResult = (String) redisTemplate.opsForHash().get(USER_LIKE_ARTICLE_KEY, String.valueOf(likedPostId));
        Set<Long> articleIdSet = userLikeResult == null ? new HashSet<>() : FastjsonUtil.deserializeToSet(userLikeResult, Long.class);
            articleIdSet.add(articleId);
        redisTemplate.opsForHash().put(USER_LIKE_ARTICLE_KEY, String.valueOf(likedPostId), FastjsonUtil.serialize(articleIdSet));

        //3.文章点赞数+1
        String articleLikedResult = (String) redisTemplate.opsForHash().get(ARTICLE_LIKED_USER_KEY, String.valueOf(articleId));
        Set<Long> likePostIdSet = articleLikedResult == null ? new HashSet<>() : FastjsonUtil.deserializeToSet(articleLikedResult, Long.class);
        likePostIdSet.add(likedPostId);
        redisTemplate.opsForHash().put(ARTICLE_LIKED_USER_KEY, String.valueOf(articleId), FastjsonUtil.serialize(likePostIdSet));
        logger.info("取消点赞数据存入redis结束,articleId:{},likedUserId:{},likedPostId:{}", articleId, likedUserId, likedPostId);
    }
}
复制代码
  • Cancel thumbs up
public void unlikeArticle(Long articleId, Long likedUserId, Long likedPostId) {
    validateParam(articleId, likedUserId, likedPostId);  //参数校验

    logger.info("取消点赞数据存入redis开始,articleId:{},likedUserId:{},likedPostId:{}", articleId, likedUserId, likedPostId);
    //1.用户总点赞数-1
    synchronized (this) {
        //只有点赞的用户才可以取消点赞
        unlikeArticleLogicValidate(articleId, likedUserId, likedPostId);
        Long totalLikeCount = Long.parseLong((String)redisTemplate.opsForHash().get(TOTAL_LIKE_COUNT_KEY, String.valueOf(likedUserId)));
         redisTemplate.opsForHash().put(TOTAL_LIKE_COUNT_KEY, String.valueOf(likedUserId), String.valueOf(--totalLikeCount));

        //2.用户喜欢的文章-1
        String userLikeResult = (String) redisTemplate.opsForHash().get(USER_LIKE_ARTICLE_KEY, String.valueOf(likedPostId));
        Set<Long> articleIdSet = FastjsonUtil.deserializeToSet(userLikeResult, Long.class);
        articleIdSet.remove(articleId);
        redisTemplate.opsForHash().put(USER_LIKE_ARTICLE_KEY, String.valueOf(likedPostId), FastjsonUtil.serialize(articleIdSet));

        //3.取消用户某篇文章的点赞数
        String articleLikedResult = (String) redisTemplate.opsForHash().get(ARTICLE_LIKED_USER_KEY, String.valueOf(articleId));
        Set<Long> likePostIdSet = FastjsonUtil.deserializeToSet(articleLikedResult, Long.class);
        likePostIdSet.remove(likedPostId);
        redisTemplate.opsForHash().put(ARTICLE_LIKED_USER_KEY, String.valueOf(articleId), FastjsonUtil.serialize(likePostIdSet));
    }

    logger.info("取消点赞数据存入redis结束,articleId:{},likedUserId:{},likedPostId:{}", articleId, likedUserId, likedPostId);
}
复制代码
  • Asynchronous for falling
@Scheduled(cron = "0 0 0/1 * * ? ")
public void redisDataToMySQL() {
    logger.info("time:{},开始执行Redis数据持久化到MySQL任务", LocalDateTime.now().format(formatter));
    //1.更新文章总的点赞数
    Map<String, String> articleCountMap = redisTemplate.opsForHash().entries(ARTICLE_LIKED_USER_KEY);
    for (Map.Entry<String, String> entry : articleCountMap.entrySet()) {
        String articleId = entry.getKey();
        Set<Long> userIdSet = FastjsonUtil.deserializeToSet(entry.getValue(), Long.class);
        //1.同步某篇文章总的点赞数到MySQL
        synchronizeTotalLikeCount(articleId, userIdSet);
        //2.同步用户喜欢的文章
        synchronizeUserLikeArticle(articleId, userIdSet);
    }
    logger.info("time:{},结束执行Redis数据持久化到MySQL任务", LocalDateTime.now().format(formatter));
}
复制代码

Description:

  • For concurrency problems by adding synchronizeachieve keywords
  • There is also an article number get thumbs up, thumbs article number method, the user points the user to achieve all the articles of praise, do not explain the method is relatively simple, you can complete the code found in

At present there is insufficient

  • Users thumbs \ cancel thumbs method, Redisthe transaction is not guaranteed
  • This application is only available in stand-alone environment, concurrency problems in distributed environments, distributed lock to be done

After November for holidays get enough

Last Attachment: The complete code addresses
welcome fork and Star , please correct me if flawed

Guess you like

Origin juejin.im/post/5da5ae056fb9a04e3043dd6c