实际使用redis场景中,可能会遇到需要大量访问redis中未知key,并对值进行相关处理的情况。下面是通过springboot整合jedis,并在单机模式下使用scan扫描key的代码,也可以避免使用keys对redis性能造成影响。

配置pom.xml

<dependency>  
 <groupId>org.springframework.boot</groupId>  
 <artifactId>spring-boot-starter-data-redis</artifactId>  
</dependency>
// 连接池
<dependency>  
 <groupId>org.apache.commons</groupId>  
 <artifactId>commons-pool2</artifactId>  
</dependency

配置application.yml

spring:  
  redis:  
  cache:  
    nodeHost: 127.0.0.1  
    port: 6379  
    commandTimeout: 5000

读取redis配置

@Data  
@Component  
@ConfigurationProperties(prefix = "spring.redis.cache")  
public class RedisProperties {  
  private int expireSeconds;  
  private String nodeHost;  
  private String port;  
  private int commandTimeout;  
}

获取jedis对象

@Slf4j  
@Configuration  
public class JedisConfig {  

  @Autowired  
  private RedisProperties redisProperties;  

  @Bean  
  public Jedis getJedis() {  
    JedisPoolConfig poolConfig = new JedisPoolConfig();  
    poolConfig.setMaxTotal(100);  
    poolConfig.setMaxIdle(20);  
    poolConfig.setMinIdle(10);  
    poolConfig.setBlockWhenExhausted(true);  
    poolConfig.setMaxWaitMillis(3000);  
    poolConfig.setTestOnBorrow(false);  
    poolConfig.setTestOnReturn(false);  
    poolConfig.setTestWhileIdle(true);  
    poolConfig.setMinEvictableIdleTimeMillis(60000);  
    poolConfig.setTimeBetweenEvictionRunsMillis(30000);  
    poolConfig.setNumTestsPerEvictionRun(-1);  

    return new JedisPool(poolConfig, redisProperties.getNodeHost(),  
              Integer.parseInt(redisProperties.getPort()), redisProperties.getExpireSeconds())  
              .getResource();  
  }  
}

使用scan读取,并进行相应处理

@Slf4j  
@Component  
public class RedisScanJob {  

  /**  
  * 单次scan查询数量 
  */  
  private static final int PAGE_SIZE = 10000;  

  @Autowired  
  private Jedis jedisClient;  

  public void doTask() {  
    ScanParams sp = new ScanParams();  
    sp.count(PAGE_SIZE);  
    deal(ScanParams.SCAN_POINTER_START, sp);  
  }  

  public void deal(String cursor, ScanParams sp) {  

    ScanResult<String> scan = jedisClient.scan(cursor, sp);  
      // 游标,标记下次scan初始位置
    cursor = scan.getStringCursor();  
        // 单次扫描获取的value集合
    List<String> keys = scan.getResult();  
    // do something ...
    if (!Objects.equals(cursor, ScanParams.SCAN_POINTER_START)) {  
      deal(cursor, sp);  
    }  
 }  
}