【Redis】對指定db進行操作


問題

自動化測試大量報錯,原因是驗證碼錯誤,從redis中查詢驗證碼,返回結果均為null。

原因

因為在UAT環境,各項目共用1個redis,db0中的數據較多,達到了600W+,導致查詢速度較慢,故驗證碼發送服務將驗證碼的存儲從db0切到了db4。

導致自定義的Jmeter函數無法正常查詢到驗證碼,因為原本該函數是默認充db0中進行查詢的。

解決方案

自定義函數中是使用jedis對redis使用操作,版本為3.0.1,maven詳細依賴如下:

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.0.1</version>
</dependency>

在網上查詢的方法有在config中添加配置與在redis對象上使用select()兩種方案,可能是因為jedis版本不同,以上2中方案均不適用。

因為JedisPoolConfig中沒有方法用於設置db,並且ShardedJedis中沒有select()方法,只能尋找其他技術方案進行解決。

函數中原使用以下方法創建redis分片:

public static ShardedJedis getJedis (String host, String password) {
    JedisShardInfo jedisShardInfo = new JedisShardInfo(host,6379);
    jedisShardInfo.setPassword(password);
    List<JedisShardInfo> list = new LinkedList<JedisShardInfo>();
    list.add(jedisShardInfo);
    ShardedJedisPool pool = new ShardedJedisPool(config, list);
    ShardedJedis jedis = pool.getResource();
    return jedis;
}

查看JedisShardInfo中的JedisShardInfo(String host, int port)構造方法,

public JedisShardInfo(String host, int port) {
    this(host, port, 2000);
}

繼續查看調用鏈,

public JedisShardInfo(String host, int port, int timeout) {
    this(host, port, timeout, timeout, 1);
}
public JedisShardInfo(String host, int port, int connectionTimeout, int soTimeout, int weight) {
    super(weight);
    this.password = null;
    this.name = null;
    this.db = 0;
    this.host = host;
    this.port = port;
    this.connectionTimeout = connectionTimeout;
    this.soTimeout = soTimeout;
}

發現db默認寫死為0,且沒有set方法。

查詢JedisShardInfo中的其他構造方法,發現JedisShardInfo(String host)方法:

public JedisShardInfo(String host) {
    super(1);
    this.password = null;
    this.name = null;
    this.db = 0;
    URI uri = URI.create(host);
    if (JedisURIHelper.isValid(uri)) {
        this.host = uri.getHost();
        this.port = uri.getPort();
        this.password = JedisURIHelper.getPassword(uri);
        this.db = JedisURIHelper.getDBIndex(uri);
        this.ssl = JedisURIHelper.isRedisSSLScheme(uri);
    } else {
        this.host = host;
        this.port = 6379;
    }
}

此處的db設置並未寫死,看起來是根據url來獲取設置,進入JedisURIHelper.getPassword()查看詳情:

public static int getDBIndex(URI uri) {
    String[] pathSplit = uri.getPath().split("/", 2);
    if (pathSplit.length > 1) {
        String dbIndexStr = pathSplit[1];
        return dbIndexStr.isEmpty() ? 0 : Integer.parseInt(dbIndexStr);
    } else {
        return 0;
    }
}

從方法中得知,db可根據url中"/"后的值進行設置,而url是通過URI.create()方法獲得,查詢URI.create()方法詳情:

public static URI create(String str) {
    try {
        return new URI(str);
    } catch (URISyntaxException x) {
        throw new IllegalArgumentException(x.getMessage(), x);
    }
}

查詢if判斷條件中的JedisURIHelper.isValid()方法:

public static boolean isValid(URI uri) {
    return !isEmpty(uri.getScheme()) && !isEmpty(uri.getHost()) && uri.getPort() != -1;

故得知,使用JedisShardInfo(String host)進行實例化時,入參為URL的形式,需要有協議頭、host地址、端口號,並在host添加"/",再其后設置dbIndex,如下所示形式:

http://xxxxxxx.redis.rds.aliyuncs.com:6379/4

結論

在自定義函數中的getJedis()方法里使用JedisShardInfo(String host)對JedisShardInfo進行實例化,並以http://redisHost:port/dbIndex的形式設置redis地址,則可對redis的指定db進行操作。

修改后的getJedis()方法如下:

public static ShardedJedis getJedis (String host, String password) {
    JedisShardInfo jedisShardInfo = new JedisShardInfo(host);
    jedisShardInfo.setPassword(password);
    List<JedisShardInfo> list = new LinkedList<JedisShardInfo>();
    list.add(jedisShardInfo);
    ShardedJedisPool pool = new ShardedJedisPool(config, list);
    ShardedJedis jedis = pool.getResource();
    return jedis;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM