当前位置:网站首页>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持久化数据。
当然也可加上限时内限制每个用户点赞次数的逻辑,防止恶意刷接口,逻辑简单,在此就不累述啦
到此 灵熙云工作室 - 实践出真理 查看全文内容
边栏推荐
猜你喜欢

Xception learning notes

Xception学习笔记

kubernetes资源对象介绍及常用命令(二)

Huawei operator level router configuration example | BGP VPLS configuration example

Completely solve the lost connection to MySQL server at 'reading initial communication packet

【小程序项目开发--京东商城】uni-app之自定义搜索组件(上)

Contrastive learning of Class-agnostic Activation Map for Weakly Supervised Object Localization and

Restcloud ETL data realizes incremental data synchronization through timestamp

MySQL index --01--- design principle of index

单片机 MCU 固件打包脚本软件
随机推荐
Add / delete / modify query summary insert/create/put/add/save/post, delete/drop/remove, update/modify/change, select/get/list/find
Codeforces Round #416 (Div. 2) C. Vladik and Memorable Trip
Restcloud ETL practice data row column conversion
Is it safe to open a stock account? Shanghai stock account opening procedures.
Densenet network paper learning notes
RestCloud ETL WebService数据同步到本地
【小程序项目开发-- 京东商城】uni-app之首页商品楼层
ipmitool下载地址和编译安装时可能出现的问题
Scale SVG to container without mask / crop
Evaluation of the entry-level models of 5 mainstream smart speakers: apple, Xiaomi, Huawei, tmall, Xiaodu, who is better?
Pychart software deployment gray unable to point
Introduction to kubernetes resource objects and common commands (II)
园区运营效率提升,小程序容器技术加速应用平台化管理
Pychar open remote directory remote host
PHP batch Excel to word
Big orange crazy blog move notice
IEDA 右键源码文件菜单简介
VMware vSphere 6.7虚拟化云管理之12、VCSA6.7更新vCenter Server许可
Mouse over effect VI
Analysis and solution of anr problems