当前位置:网站首页>巧用redis实现点赞功能,它不比mysql香吗?
巧用redis实现点赞功能,它不比mysql香吗?
2022-06-27 13:51:00 【InfoQ】
MAP_USER_LIKED被点赞用户id::点赞用户id1或者0MAP_USER_LIKED_COUNT被点赞用户idcount/**
* 将用户被其他用户点赞的数据存到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());
}
//取消点赞
@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());
}
/**
* 将被点赞用户的数量+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);
}
/**
* 获取Redis中的用户点赞详情记录
*/
@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();
//组装成 UserLike 对象
UserLikeDetail userLikeDetail = new UserLikeDetail(likedUserId, likedPostId, value);
list.add(userLikeDetail);
//存到 list 后从 Redis 中删除
redisTemplate.opsForHash().delete(RedisKeyUtils.MAP_KEY_USER_LIKED, key);
}
return list;
}
/**
* 获取Redis中的用户被点赞数量
*/
@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);
//存到 list 后从 Redis 中删除
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 '被点赞的用户id',
`liked_post_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '点赞的用户id',
`status` tinyint(1) NULL DEFAULT 1 COMMENT '点赞状态,0取消,1点赞',
`create_time` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) COMMENT '创建时间',
`update_time` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间',
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 = '用户点赞表' 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;
//同步redis的用户点赞数据到数据库
@Override
@Transactional
public void transLikedFromRedis2DB() {
List<UserLikeDetail> list = redisService.getLikedDataFromRedis();
list.stream().forEach(item->{
//查重
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);
//没有记录,直接存入
userLikeDetail.setCreateTime(LocalDateTime.now());
userLikeDetailMapper.insert(userLikeDetail);
}else{
//有记录,需要更新
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());
//点赞数量属于无关紧要的操作,出错无需抛异常
if (user != null){
Integer likeNum = user.getLikeNum() + item.getValue();
user.setLikeNum(likeNum);
//更新点赞数量
userLikeCountMapper.updateById(user);
}
});
}
边栏推荐
- 请求一下子太多了,数据库危
- A brief analysis of the differences between domestic and foreign e-commerce
- [WUSTCTF2020]girlfriend
- 基于 Nebula Graph 构建百亿关系知识图谱实践
- 【业务安全-04】万能用户名及万能密码实验
- 【mysql进阶】MTS主从同步原理及实操指南(七)
- Dynamic Networks and Conditional Computation论文简读和代码合集
- Rereading the classic: the craft of research (1)
- 【业务安全-01】业务安全概述及测试流程
- 剑指 Offer II 039. 直方图最大矩形面积 单调栈
猜你喜欢

Pytorch learning 3 (test training model)

Semaphore of thread synchronization

How to set the compatibility mode of 360 speed browser
![[business security 03] password retrieval business security and interface parameter account modification examples (based on the metinfov4.0 platform)](/img/29/73c381f14a09ecaf36a98d67d76720.png)
[business security 03] password retrieval business security and interface parameter account modification examples (based on the metinfov4.0 platform)

Does Xinhua San still have to rely on ICT to realize its 100 billion enterprise dream?

Deep understanding of bit operations
![[OS command injection] common OS command execution functions and OS command injection utilization examples and range experiments - based on DVWA range](/img/f2/458770fc74971bef23f96f87733ee5.png)
[OS command injection] common OS command execution functions and OS command injection utilization examples and range experiments - based on DVWA range
![[安洵杯 2019]Attack](/img/1a/3e82a54cfcb90ebafebeaa8ee1ec01.png)
[安洵杯 2019]Attack
![[business security-04] universal user name and universal password experiment](/img/09/73d8356d00cefb6d1af086669f69ff.png)
[business security-04] universal user name and universal password experiment

关于接口测试自动化的总结与思考
随机推荐
Daily 3 questions (1): find the nearest point with the same X or Y coordinate
Domestic database disorder
剑指 Offer II 039. 直方图最大矩形面积 单调栈
Prometheus 2.26.0 new features
[business security 03] password retrieval business security and interface parameter account modification examples (based on the metinfov4.0 platform)
How to use 200 lines of code to implement Scala's Object Converter
线程同步之信号量
How to solve the problem of missing language bar in win10 system
Overseas warehouse knowledge popularization
【业务安全03】密码找回业务安全以及接口参数账号修改实例(基于metinfov4.0平台)
对半查找(折半查找)
Summary and Thinking on interface test automation
EventLoop learning
Dynamic Networks and Conditional Computation论文简读和代码合集
NLP - monocleaner
Gaode map IP positioning 2.0 backup
Learning records of numpy Library
[XMAN2018排位赛]通行证
Too many requests at once, and the database is in danger
awk 简明教程