java中Jedis对redis内数据的批量获取- hscan,Pipeline的使用- 常用工具类-RedisUtil
指出问题
在使用redis的时候,配合jedis使用,但是发现jedis的keys* 或者mget都会造成redis阻塞,所以使用了redis的解决方案Pipeline(管道)的方式进行对redis内数据的获取。封装了以下工具类。需要自取。或者提供好的方法可以留言,我可以写进来。
初始化配置
先在application.yml配置redis基本信息
spring:
redis:
host: 127.0.0.1
port: 6379
password:
database: 0
timeout: 5000
创建jedis连接池
创建RedisConfig.java
@Configuration
@Slf4j
public class RedisConfig {
@Autowired
private RedisProperties redisProperties; //从配置文件获取redis连接配置
private JedisPool jedisPool;
@Autowired
private JedisPoolConfig jedisPoolConfig;
@Bean
@Scope("prototype")
/**
* 多例模式返回redis客户端,但是在依赖注入时,建议不要使用
* 因为jedis客户端是阻塞式IO的,而且线程不安全,
* 所以在操作数据库的时候不要使用单例,建议从连接池获取
*/
public redis.clients.jedis.Jedis jedis(){
if (jedisPool!=null){
return jedisPool.getResource();
}else {
return jedisPool().getResource();
}
// return jedisPool.getResource();
}
@Bean
/**
* 单例模式返回redis连接池
* 依赖注入时,建议注入jedisPool,获取连接池,然后调用getResource方法获取jedis客户端
* 使用完后,调用jedis.close()方法归还连接,节约资源
*/
public JedisPool jedisPool(){
synchronized (this){
if(jedisPool==null){
synchronized (this){
if (StringUtils.isEmpty(redisProperties.getPassword())){
//无密码
jedisPool = new JedisPool(jedisPoolConfig,redisProperties.getHost(),redisProperties.getPort(),(int)redisProperties.getTimeout().toMillis());
}else {//有密码
jedisPool = new JedisPool(jedisPoolConfig,redisProperties.getHost(),redisProperties.getPort(),(int)redisProperties.getTimeout().toMillis(),redisProperties.getPassword());
}
}
}
}
return jedisPool;
}
@Bean
public JedisPoolConfig jedisPoolConfig(){
// Jedis连接池配置
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(redisProperties.getLettuce().getPool().getMaxActive());
// 最大空闲连接数, 默认8个
// jedisPoolConfig.setMaxIdle(50);
jedisPoolConfig.setMaxIdle(redisProperties.getLettuce().getPool().getMaxIdle());
// 最大连接数, 默认8个
// jedisPoolConfig.setMaxTotal(300);
//最小空闲连接数, 默认0
jedisPoolConfig.setMinIdle(redisProperties.getLettuce().getPool().getMinIdle());
// jedisPoolConfig.setMinIdle(20);
// 获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常, 小于零:阻塞不确定的时间, 默认-1
jedisPoolConfig.setMaxWaitMillis(redisProperties.getLettuce().getPool().getMaxWait().toMillis()); // 设置10秒
// jedisPoolConfig.setMaxWaitMillis(3000); // 设置2秒
//对拿到的connection进行validateObject校验
jedisPoolConfig.setTestOnBorrow(true);
return jedisPoolConfig;
}
}
jedis工具类
@Component
@Slf4j
public class RedisUtil {
@Autowired
private JedisPool jedisPool;
/**
* findValueByKeyOfPipeline和 findValueByKeyOfPipelineMget 的区别在于 前者根据阈值获取多次 后者是直接一次性获取
*/
/**
* 根据(不完整)key值通过Pipeline的方式获取值
* 先通过scan获取全部的key,再通过Pipeline获取全部的值
* 根据countVPT 这个 阈值来控制 获取多次
* (通过建立一个管道一次提交)
* @param redisKey
* @Auther erpangshou
* @Date:2021/6/17 10:36
**/
public List findValueByKeyOfPipeline(String redisKey) {
Jedis jedis = null;
List values = new ArrayList<>();
ArrayList>> responses = new ArrayList<>();
int countVPT=ConstantCom.BATCH_SIZE;
try {
jedis = jedisPool.getResource();
//从redis获取值刷新航迹信息
List allKeys = findAllKeys(redisKey);
if (Objects.isNull(allKeys) || allKeys.isEmpty()) {
return values;
}
Pipeline pipelined = jedis.pipelined();
ArrayList strings = new ArrayList<>();
for (String key : allKeys) {
strings.add(key);
if (strings.size()==countVPT){
ArrayList subList = new ArrayList<>(strings);
String[] keys = subList.toArray(new String[subList.size()]);
Response> mget = pipelined.mget(keys);
responses.add(mget);
strings=new ArrayList<>();
}
}
//最后的数据
String[] keys = strings.toArray(new String[strings.size()]);
Response> mget = pipelined.mget(keys);
responses.add(mget);
pipelined.sync();
for (Response> respons : responses) {
values.addAll(respons.get());
}
} catch (Exception e) {
e.printStackTrace();
log.error("redis查询异常:" + e.getMessage());
} finally {
if (jedis != null) {
jedis.close();
}
}
return values;
}
/**
* 根据(不完整)key值通过Pipeline的方式获取值
* 先通过scan获取全部的key,再通过Pipeline获取全部的值
* (通过Pipeline.mget直接获取)
* @param redisKey
* @Auther erpangshou
* @Date:2021/6/17 10:36
**/
public List findValueByKeyOfPipelineMget(String redisKey) {
Jedis jedis = null;
List values = new ArrayList<>();
ArrayList>> responses = new ArrayList<>();
try {
jedis = jedisPool.getResource();
//从redis获取值刷新航迹信息
List allKeys = findAllKeys(redisKey);
if (Objects.isNull(allKeys) || allKeys.isEmpty()) {
return values;
}
// allKeys=allKeys.subList(0,5000);
String[] keys = allKeys.toArray(new String[allKeys.size()]);
Pipeline pipelined = jedis.pipelined();
Response> mget = pipelined.mget(keys);
pipelined.sync();
values=mget.get();
} catch (Exception e) {
log.error("redis查询异常:" + e.getMessage());
} finally {
if (jedis != null) {
jedis.close();
}
}
return values;
}
/**
* jedis的met
* @param redisKey
* @Auther erpangshou
* @return
*/
public List mget(String redisKey) {
Jedis jedis = null;
List values = new ArrayList<>();
try {
jedis = jedisPool.getResource();
//从redis获取值刷新航迹信息
List allKeys = findAllKeys(redisKey);
if (Objects.isNull(allKeys) || allKeys.isEmpty()) {
return values;
}
String[] keys = allKeys.toArray(new String[allKeys.size()]);
List mget1 = jedis.mget(keys);
values=mget1;
} catch (Exception e) {
log.error("redis查询异常:" + e.getMessage());
} finally {
if (jedis != null) {
jedis.close();
}
}
return values;
}
/**
* 根据(不完整)key值通过Pipeline的方式获取值 --使用传入jedis的方式
* 先通过scan获取全部的key,再通过Pipeline获取全部的值
*
* @param redisKey
* @Auther erpangshou
* @Date:2021/6/17 10:36
**/
public List findValueByKeyOfPipeline(String redisKey, Jedis jedis) {
List values = new ArrayList<>();
try {
//从redis获取值刷新航迹信息
List allKeys = findAllKeys(redisKey);
if (allKeys == null || allKeys.isEmpty()) {
return values;
}
//此处采用Pipeline,以提升性能
Pipeline pipelined = jedis.pipelined();
Response> mget = pipelined.mget(allKeys.toArray(new String[allKeys.size()]));
pipelined.sync();
values = mget.get();
} catch (Exception e) {
log.error("redis查询异常:" + e.getMessage());
}
return values;
}
/**
* 根据多个完整(精确)key值通过Pipeline的方式获取值
* 使用完整的key通过Pipeline获取全部的值
*
* @param allKeys
* @Auther erpangshou
* @Date 2021/6/17 10:33
*/
public List findAllkeysByKeysOfPipeline(String[] allKeys) {
Jedis jedis = null;
List values = new ArrayList<>();
int countVPT=ConstantCom.BATCH_SIZE;
try {
jedis = jedisPool.getResource();
ArrayList>> responses = new ArrayList<>();
//从redis获取值刷新航迹信息
if (Objects.isNull(allKeys) || allKeys.length == 0) {
return values;
}
//此处采用Pipeline,以提升性能
Pipeline pipelined = jedis.pipelined();
ArrayList strings = new ArrayList<>();
for (String key : allKeys) {
strings.add(key);
if (strings.size()==countVPT){
ArrayList subList = new ArrayList<>(strings);
String[] keys = subList.toArray(new String[subList.size()]);
Response> mget = pipelined.mget(keys);
responses.add(mget);
strings=new ArrayList<>();
}
}
//最后的数据
String[] keys = strings.toArray(new String[strings.size()]);
Response> mget = pipelined.mget(keys);
responses.add(mget);
pipelined.sync();
for (Response> respons : responses) {
values.addAll(respons.get());
}
} catch (Exception e) {
log.error("redis查询异常:" + e.getMessage());
} finally {
if (jedis != null) {
jedis.close();
}
}
return values;
}
/**
* 根据多个完整(精确)key值通过Pipeline的方式获取值 --使用传入jedis的方式
* 使用完整的key通过Pipeline获取全部的值
*
* @param redisKeys
* @Auther erpangshou
* @Date 2021/6/17 10:33
*/
public List findAllkeysByKeysOfPipeline(String[] redisKeys, Jedis jedis) {
List values = new ArrayList<>();
try {
//从redis获取值刷新航迹信息
if (redisKeys == null || redisKeys.length == 0) {
return values;
}
//此处采用Pipeline,以提升性能
Pipeline pipelined = jedis.pipelined();
Response> mget = pipelined.mget(redisKeys);
pipelined.sync();
values = mget.get();
} catch (Exception e) {
log.error("redis查询异常:" + e.getMessage());
}
return values;
}
/**
* 根据keys 获取value
*
* @param pattern
* @Auther erpangshou
*/
public List findValueByKey(String pattern) {
List values = null;
List keys = findAllKeys(pattern);
if (keys != null && keys.size() > 0) {
String[] strings = keys.toArray(new String[keys.size()]);
values = findAllkeysByKeysOfPipeline(strings);
}
return values;
}
/**
* 根据keys 获取value --使用传入jedis的方式
*
* @param pattern
* @Auther erpangshou
*/
public List findValueByKey(String pattern, Jedis jedis) {
List values = null;
List keys = findAllKeys(pattern);
if (keys != null && keys.size() > 0) {
String[] strings = keys.toArray(new String[keys.size()]);
values = findAllkeysByKeysOfPipeline(strings, jedis);
}
return values;
}
/**
* 根据keys 获取value 已map形式返回
*
* @param pattern
* @Auther erpangshou
*/
public List