代码讲解:5-点赞功能-定时持久化到数据库-pipeline+lua-优化ByScan_哔哩哔哩_bilibili
https://www.bilibili.com/video/BV1Gs4y1676q
代码:
blogLike_schedule/like05 · xin麒/XinQiUtilsOrDemo - 码云 - 开源中国 (gitee.com)
https://gitee.com/flowers-bloom-is-the-sea/XinQiUtilsOrDemo/tree/master/blogLike_schedule/like05
数据库表:
blogLike_schedule · xin麒/XinQiUtilsOrDemo - 码云 - 开源中国 (gitee.com)
这篇文章是根据上一篇文章:(108条消息) springboot+redis+mysql+quartz-通过Java操作redis的KEYS*命令获取缓存数据定时更新数据库_xin麒的博客-CSDN博客
https://blog.csdn.net/ws_please/article/details/131621669
进行的优化。
1、重要依赖:
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
2、配置jedis:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import org.springframework.beans.factory.annotation.Value;
@Configuration
public class JedisConfig {
private Logger logger = LoggerFactory.getLogger(JedisConfig.class);
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.password}")
private String password;
@Value("${spring.redis.timeout}")
private int timeout;
@Value("${spring.redis.jedis.pool.max-active}")
private int maxActive;
@Value("${spring.redis.jedis.pool.max-idle}")
private int maxIdle;
@Value("${spring.redis.jedis.pool.min-idle}")
private int minIdle;
@Bean
public JedisPool jedisPool(){
JedisPoolConfig jedisPoolConfig=new JedisPoolConfig();
jedisPoolConfig.setMaxIdle(maxIdle);
jedisPoolConfig.setMinIdle(minIdle);
jedisPoolConfig.setMaxTotal(maxActive);
JedisPool jedisPool=new JedisPool(jedisPoolConfig,host,port,timeout,password);
logger.info("JedisPool连接成功:"+host+"\t"+port);
return jedisPool;
}
}
定时板块就看这篇吧:
https://blog.csdn.net/ws_please/article/details/131621669
3、这里大体上的内容和上一篇文章差不多的,就是从缓存获取数据的方法换成了scan:
//这里就执行所有博客的likeList入库吧
@Override
public void updateAllLikeListToDatabase() {
String prefix = "BLOG_LIKED_KEY";
// Set keys = getAllRedisKeyByKeys(prefix);//这个不行!
Set<String> keys = getAllRedisKeyByScanThroughMatch(prefix);
if (keys == null || keys.size() == 0) return;
for (String key : keys) {
Map<String, String> map = queryAllBlogLikesUserIdWithScoresByRedisKey(key);
//get blogId,,这个blogId是在后半段的。
Long blogId = Long.parseLong(key.substring(prefix.length(), key.length()));
durableToDatabaseByBlogIdAndMap(map,blogId);
}
}
先通过jedis的scan方法模糊匹配出所有博客id的键
//通过scan来模糊匹配
public Set<String> getAllRedisKeyByScanThroughMatch(String prefix) {//找不到stringRedisTemplate对Zset里键值对扫描的资料
Jedis jedis = null;
Set<String> blogLikeList = new HashSet<>();
ScanParams scanParams = new ScanParams();
try {
jedis = jedisPool.getResource();
String cursor = "0";
do {
// 扫描并获取一部分key
ScanResult<String> result = jedis.scan(cursor, scanParams.match(prefix.concat("*")));
// 记录cursor
cursor = result.getCursor();
List<String> list = result.getResult();
if (list == null || list.isEmpty()) {
break;
}
// 遍历
for (String key : list) {
// 判断key的类型
log.debug("key is {}", key);//这里可以看到有哪些key
//符合就要,不符合就不要
blogLikeList.add(key);
}
} while (!cursor.equals("0"));
} catch (Exception e) {
e.printStackTrace();
} finally {
if (jedis != null) jedis.close();
}
return blogLikeList;
}
再通过stringRedisTemplate
得到某篇博客的所有点赞信息:
private Map<String, String> queryAllBlogLikesUserIdWithScoresByRedisKey(String key) {
Set<String> stringUserIdList = stringRedisTemplate.opsForZSet().range(key, 0, -1);
if (stringUserIdList == null || stringUserIdList.size() == 0) return new HashMap<>();
List<String> ids = stringUserIdList.stream().map(String::valueOf).collect(Collectors.toList());
HashMap<String, String> userIdWithTime = new HashMap<>();
for (String userId : stringUserIdList) {//暂时找不到可以直接返回List的api
String score = stringRedisTemplate.opsForZSet().score(key, userId).toString();
userIdWithTime.put(userId, score);
}
return userIdWithTime;
}
其他和https://blog.csdn.net/ws_please/article/details/131621669基本一致。
还可以继续优化,比如使用pipeline技术:
(108条消息) springboot+redis+mysql+quartz-通过Java操作jedis使用pipeline获取缓存数据定时更新数据库_xin麒的博客-CSDN博客
https://blog.csdn.net/ws_please/article/details/131623267
或者说用lua脚本也可以:
(108条消息) springboot+redis+mysql+quartz-通过Java操作jedis定时使用lua脚本获取缓存数据并更新数据库_xin麒的博客-CSDN博客
https://blog.csdn.net/ws_please/article/details/131623224
现在是2023-07-01,不得不吐槽stringRedisTemplate
,对于scan扫描好像stringRedisTemplate
的方法是找不到的,jedis
的参考资料非常丰富,全网几乎搜不到stringRedisTemplate
对zset数据的scan操作信息,官网也很少资料(可能没细看),笑死,所以后面就用jedis
来实现了。
其他类似的文章:
(108条消息) springboot+redis+mysql+quartz-通过Java操作redis的KEYS*命令获取缓存数据定时更新数据库_xin麒的博客-CSDN博客
(108条消息) springboot+redis+mysql+quartz-通过Java操作jedis定时使用lua脚本获取缓存数据并更新数据库_xin麒的博客-CSDN博客
(108条消息) lua脚本获取table类型-Java使用lua脚本操作redis获取zset元素的集合_xin麒的博客-CSDN博客
(108条消息) springboot+redis+mysql+quartz-通过Java操作jedis使用pipeline获取缓存数据定时更新数据库_xin麒的博客-CSDN博客
(108条消息) springboot+redis+mysql+quartz-通过Java操作jedis的scan命令获取缓存数据定时更新数据库_xin麒的博客-CSDN博客