当前位置:网站首页>Using redis skillfully to realize the like function, isn't it more fragrant than MySQL?
Using redis skillfully to realize the like function, isn't it more fragrant than MySQL?
2022-06-27 14:06:00 【InfoQ】
MAP_USER_LIKED Be liked by users id:: Like user id1 perhaps 0MAP_USER_LIKED_COUNT Be liked by users idcount/**
* Save the data that users like by other users to redis
*/
@Override
public void saveLiked2Redis(String likedUserId, String likedPostId) {
String key = RedisKeyUtils.getLikedKey(likedUserId, likedPostId);
redisTemplate.opsForHash().put(RedisKeyUtils.MAP_KEY_USER_LIKED,key, LikedStatusEnum.LIKE.getCode());
}
// Cancel likes
@Override
public void unlikeFromRedis(String likedUserId, String likedPostId) {
String key = RedisKeyUtils.getLikedKey(likedUserId, likedPostId);
redisTemplate.opsForHash().put(RedisKeyUtils.MAP_KEY_USER_LIKED,key,LikedStatusEnum.UNLIKE.getCode());
}
/**
* Number of users who will be liked +1
*/
@Override
public void incrementLikedCount(String likedUserId) {
redisTemplate.opsForHash().increment(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT,likedUserId,1);
}
//-1
@Override
public void decrementLikedCount(String likedUserId) {
redisTemplate.opsForHash().increment(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, likedUserId, -1);
}
/**
* obtain Redis User likes details record in
*/
@Override
public List<UserLikeDetail> getLikedDataFromRedis() {
Cursor<Map.Entry<Object,Object>> scan = redisTemplate.opsForHash().scan(RedisKeyUtils.MAP_KEY_USER_LIKED, ScanOptions.NONE);
List<UserLikeDetail> list = new ArrayList<>();
while (scan.hasNext()){
Map.Entry<Object, Object> entry = scan.next();
String key = (String) entry.getKey();
String[] split = key.split("::");
String likedUserId = split[0];
String likedPostId = split[1];
Integer value = (Integer) entry.getValue();
// Assemble into UserLike object
UserLikeDetail userLikeDetail = new UserLikeDetail(likedUserId, likedPostId, value);
list.add(userLikeDetail);
// Deposit in list From Redis Delete in
redisTemplate.opsForHash().delete(RedisKeyUtils.MAP_KEY_USER_LIKED, key);
}
return list;
}
/**
* obtain Redis The number of users like in
*/
@Override
public List<UserLikCountDTO> getLikedCountFromRedis() {
Cursor<Map.Entry<Object,Object>> cursor = redisTemplate.opsForHash().scan(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, ScanOptions.NONE);
List<UserLikCountDTO> list = new ArrayList<>();
while(cursor.hasNext()){
Map.Entry<Object, Object> map = cursor.next();
String key = (String) map.getKey();
Integer value = (Integer) map.getValue();
UserLikCountDTO userLikCountDTO = new UserLikCountDTO(key,value);
list.add(userLikCountDTO);
// Deposit in list From Redis Delete in
redisTemplate.opsForHash().delete(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT,key);
}
return list;
}


DROP TABLE IF EXISTS `user_like_detail`;
CREATE TABLE `user_like_detail` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`liked_user_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT ' Liked users id',
`liked_post_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT ' Thumb up users id',
`status` tinyint(1) NULL DEFAULT 1 COMMENT ' Like status ,0 Cancel ,1 give the thumbs-up ',
`create_time` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) COMMENT ' Creation time ',
`update_time` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) ON UPDATE CURRENT_TIMESTAMP(0) COMMENT ' Modification time ',
PRIMARY KEY (`id`) USING BTREE,
INDEX `liked_user_id`(`liked_user_id`) USING BTREE,
INDEX `liked_post_id`(`liked_post_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = ' The user likes the watch ' ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
DROP TABLE IF EXISTS `user_like_count`;
CREATE TABLE `user_like_count` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`like_num` int(11) NULL DEFAULT 0,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
// Sync redis The user likes the data to the database
@Override
@Transactional
public void transLikedFromRedis2DB() {
List<UserLikeDetail> list = redisService.getLikedDataFromRedis();
list.stream().forEach(item->{
// Duplicate check
UserLikeDetail userLikeDetail = userLikeDetailMapper.selectOne(new LambdaQueryWrapper<UserLikeDetail>()
.eq(UserLikeDetail::getLikedUserId, item.getLikedUserId())
.eq(UserLikeDetail::getLikedPostId, item.getLikedPostId()));
if (userLikeDetail == null){
userLikeDetail = new UserLikeDetail();
BeanUtils.copyProperties(item, userLikeDetail);
// There is no record , Deposit directly into
userLikeDetail.setCreateTime(LocalDateTime.now());
userLikeDetailMapper.insert(userLikeDetail);
}else{
// Records , You need to update
userLikeDetail.setStatus(item.getStatus());
userLikeDetail.setUpdateTime(LocalDateTime.now());
userLikeDetailMapper.updateById(item);
}
});
}
@Override
@Transactional
public void transLikedCountFromRedis2DB() {
List<UserLikCountDTO> list = redisService.getLikedCountFromRedis();
list.stream().forEach(item->{
UserLikeCount user = userLikeCountMapper.selectById(item.getKey());
// The number of likes is irrelevant , You don't need to throw exceptions if you make mistakes
if (user != null){
Integer likeNum = user.getLikeNum() + item.getValue();
user.setLikeNum(likeNum);
// Update likes
userLikeCountMapper.updateById(user);
}
});
}
边栏推荐
- Redis持久化
- [daily 3 questions (3)] maximum number of balls in the box
- 海量数据!秒级分析!Flink+Doris构建实时数仓方案
- Make a ThreadLocal (source code) that everyone can understand
- 【业务安全-04】万能用户名及万能密码实验
- [WUSTCTF2020]girlfriend
- Quickly set up a website to visit foreign countries, set up SS and start BBR to quickly surf the Internet
- Number of printouts (solved by recursive method)
- Pytorch learning 1 (learning documents on the official website)
- PostgreSQL 15新版本特性解读(含直播问答、PPT资料汇总)
猜你喜欢
随机推荐
Axi bus
Shell concise tutorial
海外仓知识科普
【业务安全-04】万能用户名及万能密码实验
MySQL locking mechanism and four isolation levels
[business security 03] password retrieval business security and interface parameter account modification examples (based on the metinfov4.0 platform)
Type 'image' is not a subtype of type 'imageprovider < object > solution
为什么 Oracle 云客户必须在Oracle Cloud 季度更新发布后自行测试?
Deep understanding of bit operations
Getting to know cloud native security for the first time: the best guarantee in the cloud Era
What if the win system cannot complete the update and is revoking the status change
[WUSTCTF2020]girlfriend
关于接口测试自动化的总结与思考
A brief analysis of the differences between domestic and foreign e-commerce
Crane: a new way of dealing with dictionary items and associated data
Four characteristics of transactions
Summary of basic usage of command line editor sed
剑指 Offer II 039. 直方图最大矩形面积 单调栈
Kyndryl partnered with Oracle and Veritas
The second part of the travel notes of C (Part II) structural thinking: Zen is stable; all four advocate structure



![[WUSTCTF2020]girlfriend](/img/a8/33fe5feb7bcbb73ba26a94d226cc4d.png)
![[PHP code injection] common injectable functions of PHP language and utilization examples of PHP code injection vulnerabilities](/img/19/9827a5e8becfc9d5bf2f51bddf803e.png)



