当前位置:网站首页>Redis高效点赞与取消功能
Redis高效点赞与取消功能
2022-07-01 02:57:00 【靈熙雲】
到此 灵熙云工作室 - 实践出真理 查看全文内容

像CSDN的点赞功能只记录了数量,微信朋友圈的点赞功能有显示点赞人头像(获取userId查询用户信息封装返回即可)
点赞、取消点赞是高频次的操作,若每次都读写数据库,大量的操作会影响数据库性能,甚至宕机,所以用缓存处理再合适不过。本文以文章点赞为例来展开叙述
数据格式选择
Redis有5种数据结构分别为:String(字符串)、List(列表)、Set(集合)、Hash(散列)、Zset(有序集合)。
由于需要记录文章和点赞人,还有点赞状态(点赞、取消),分析下 Redis 数据格式中Hash最合适。
因为Hash里的数据都是存在一个Key中,通过Key很方便的把所有的点赞数据都取出。Key里面的数据还可以存成键值对的形式,方便存入点赞人、被点赞人和点赞状态。
文章 id为articleId,点赞人的 id为userId,点赞状态为1(点赞)和0(取消点赞)。文章 id和点赞人 id作为HashKey,两个 id 中间用::隔开,点赞状态作为HashValue。

整合SpringBoot
依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
基础配置
spring:
redis:
database: 0
host: 127.0.0.1
port: 6379
jedis:
pool:
max-active: 8
max-wait: -1ms
max-idle: 8
min-idle: 0
配置类
package cn.goitman.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
import java.sql.SQLException;
/** * @author Nicky * @version 1.0 * @className RedisConfig * @blog goitman.cn | blog.csdn.net/minkeyto * @description Redis配置类 * @date 2022/5/16 14:40 */
@Configuration
public class RedisConfig {
/** * 凡事使用到template的redis操作都必须走@Transanctional注解式事务,要不然会导致连接一直占用,不关闭 */
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory){
RedisTemplate template = new RedisTemplate();
// 改变redisTemplate的序列化方式,key为字符串格式,value为json格式
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
// HashKey 和 HashValue 为json格式
template.setHashKeySerializer(new GenericJackson2JsonRedisSerializer());
template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
template.setConnectionFactory(redisConnectionFactory);
// 开启事务支持
template.setEnableTransactionSupport(true);
return template;
}
/** * 配置事务管理器 */
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) throws SQLException {
return new DataSourceTransactionManager(dataSource);
}
}
如果redisTemplate没有序列化,在可视化工具中看到的数据为乱码,获取数据时也可能为空,模糊查询(下文有叙述)功能也使用不了

Redis接口
package cn.goitman.service.impl;
import cn.goitman.pojo.Article;
import cn.goitman.pojo.Likes;
import cn.goitman.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/** * @author Nicky * @version 1.0 * @className RedisServiceImpl * @blog goitman.cn | blog.csdn.net/minkeyto * @description Redis接口实现类 * @date 2022/5/13 16:43 */
@Service
@Transactional
public class RedisServiceImpl implements RedisService {
// 文章点赞 KEY
public static final String KEY_ARTICLE_LIKE = "ARTICLE_LIKE";
// 文章点赞数量 KEY
public static final String KEY_ARTICLE_LIKE_COUNT = "ARTICLE_LIKE_COUNT";
@Autowired
RedisTemplate redisTemplate;
/** * 保存点赞和文章点赞量 */
@Override
public void saveLike(String articleId, String userId) {
String field = getLikeKey(articleId, userId);
redisTemplate.opsForHash().put(KEY_ARTICLE_LIKE, field, 1);
redisTemplate.opsForHash().increment(KEY_ARTICLE_LIKE_COUNT, articleId, 1);
}
/** * 取消点赞和文章点赞量 */
@Override
public void unLike(String articleId, String userId) {
String field = getLikeKey(articleId, userId);
redisTemplate.opsForHash().put(KEY_ARTICLE_LIKE, field, 0);
redisTemplate.opsForHash().increment(KEY_ARTICLE_LIKE_COUNT, articleId, -1);
}
/** * 删除点赞数据 */
@Override
public void deleteLike(List<Likes> list) {
for (Likes like : list) {
String field = getLikeKey(like.getArticleId(), like.getUserId());
redisTemplate.opsForHash().delete(KEY_ARTICLE_LIKE, field);
}
}
/** * 删除文章点赞量数据 */
@Override
public void deleteLikeCount(String articleId) {
redisTemplate.opsForHash().delete(KEY_ARTICLE_LIKE_COUNT, articleId);
}
/** * 获取全部点赞数据 */
@Override
public List<Likes> getAllLikeData() {
List<Likes> list = new ArrayList<>();
Cursor<Map.Entry<Object, Object>> cursor = redisTemplate.opsForHash().scan(KEY_ARTICLE_LIKE, ScanOptions.NONE);
while (cursor.hasNext()) {
Map.Entry<Object, Object> entry = cursor.next();
String keys = entry.getKey().toString();
String[] keyArr = keys.split("::");
Likes like = new Likes(keyArr[0], keyArr[1], (Integer) entry.getValue());
list.add(like);
}
return list;
}
/** * 获取文章点赞量数据 */
@Override
public List<Article> getArticleLikeCount() {
List<Article> list = new ArrayList<>();
Cursor<Map.Entry<Object, Object>> cursor = redisTemplate.opsForHash().scan(KEY_ARTICLE_LIKE_COUNT, ScanOptions.NONE);
while (cursor.hasNext()) {
Map.Entry<Object, Object> entry = cursor.next();
String articleId = entry.getKey().toString();
Article article = new Article(articleId, (Integer) entry.getValue());
list.add(article);
}
return list;
}
/** * 拼接文章ID和点赞人ID作为key */
private String getLikeKey(String articleId, String userId) {
return new StringBuilder().append(articleId).append("::").append(userId).toString();
}
}
搞掂,就是这么简单高效,在Redis内,存在相同数据只会修改value,并且Redis默认RDB持久化数据。
当然也可加上限时内限制每个用户点赞次数的逻辑,防止恶意刷接口,逻辑简单,在此就不累述啦
到此 灵熙云工作室 - 实践出真理 查看全文内容
边栏推荐
- Optimal Transport系列1
- 性能测试常见面试题
- Add / delete / modify query summary insert/create/put/add/save/post, delete/drop/remove, update/modify/change, select/get/list/find
- Huawei operator level router configuration example | configuration optionA mode cross domain LDP VPLS example
- 鼠标悬停效果五
- 大橙子疯博客搬家通知
- Codeforces Round #416 (Div. 2) C. Vladik and Memorable Trip
- MySQL index --01--- design principle of index
- [linear DP] longest common subsequence
- Contrastive learning of Class-agnostic Activation Map for Weakly Supervised Object Localization and
猜你喜欢

【小程序项目开发-- 京东商城】uni-app之分类导航区域

servlet【初识】

XXL job User Guide

Restcloud ETL practice to realize incremental data synchronization without identification bit
![Install vcenter6.7 [vcsa6.7 (vCenter server appliance 6.7)]](/img/83/e3c9d8eda9d5351d4c54928d3b090b.png)
Install vcenter6.7 [vcsa6.7 (vCenter server appliance 6.7)]

lavaweb【初识后续问题的解决】

Const and the secret of pointers

Xception学习笔记

Evaluation of the entry-level models of 5 mainstream smart speakers: apple, Xiaomi, Huawei, tmall, Xiaodu, who is better?

园区运营效率提升,小程序容器技术加速应用平台化管理
随机推荐
Cloud native annual technology inventory is released! Ride the wind and waves at the right time
Mnasnet learning notes
Introduction and basic knowledge of machine learning
Mouse over effect II
[machine learning] vectorized computing -- a must on the way of machine learning
MySQL index --01--- design principle of index
Mouse over effect VI
Mouse over effect 7
servlet【初识】
PCB defect detection based on OpenCV and image subtraction
Sampling Area Lights
产业互联网中,「小」程序有「大」作为
Lenovo x86 server restart management controller (xclarity controller) or TSM method
Sampling Area Lights
Mouse over effect III
robots.txt限制搜索引擎收录
PTA 1016
Restcloud ETL实践之数据行列转换
园区运营效率提升,小程序容器技术加速应用平台化管理
Why are strings immutable in many programming languages? [repeated] - why are strings immutable in many programming languages? [duplicate]