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
MySQL
database
Database Design
-
Redis database design
Redis
isK-V
the database, there is no uniform data structure, designed for different functions with different points ofK-V
storage structure- Like several points of an article using the user
HashMap
data structureHashMap
iskey
asarticleId
,value
asSet
,Set
the value of the userID
, i.e.,HashMap<String, Set<String>>
- Like the total number of points the user to use
HashMap
the data structure,HashMap
thekey
isuserId
,value
toString
record the total number of thumbs - Like the user point of use of the article in
HashMap
a data structure,HashMap
thekey
isuserId
,value
asSet
,Set
in the value of the articleID
, i.e.,HashMap<String, Set<String>>
- Like several points of an article using the user
-
MySQL database design, the most important two tables,
article
tables anduser_like_article
article
Table 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
Redis
to synchronize the number of points Chanuser_like_article
Table 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_modified
field
flow chart
Flowchart is relatively simple, and the cancel point Like steps to achieve substantially the same point Like
- Parameter check incoming parameter
null
value 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
Redis
into 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
Redis
read data into the persistenceMySQL
of
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
synchronize
achieve 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,
Redis
the 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