Redis_Jedis, JedisCluster 扩展 keys 方法实现

 

最近,我们使用 Java 操作 Redis 比较多,用的组件是 Jedis ,下面是一个 maven 坐标。


    redis.clients
    jedis
    2.9.0
    jar
    compile

 

其中操作 Redis 主要使用以下3个类,

Jedis   :

    用于操作单节点Redis.

SharedJedis :

    用于操作分片Redis 集群,较老的方式,Redis 集群下,使用 JedisCluster 进行替代。

JedisCluster :

   Redis 新增加的 Redis 集群模式下的操作类。 

 

      但是 JedisCluster 从性能方面等考虑,并没有提供 Jedis 下提供的 keys 方法, 

keys 方法, 主要用于 通配符 模式匹配 返回满足条件 的 key。

keys 方法 还是比较有用的。

所以我们来扩展一下。

 

首先,我们定义一个接口,用于我们进行功能的扩展。

 

接口类:

RedisClusterOperator.java 
package com.redis.extend;

import java.util.Set;

/**
 * Created by szh on 2018/10/16.
 *
 * @author szh
 */
public interface RedisClusterOperator {

    Set keys(String pattern);

}

 

 

实现类:

RedisClusterExtCmd.java
package com.redis.extend.impl;

import com.redis.extend.RedisClusterOperator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPool;

import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

/**
 * Created by szh on 2018/10/16.
 *
 * @author szh
 */
public class RedisClusterExtCmd implements RedisClusterOperator {

    public final static Logger logger = LoggerFactory.getLogger(RedisClusterOperator.class);

    private JedisCluster jedisCluster = null;

    public RedisClusterExtCmd(JedisCluster jedisCluster) {
        this.jedisCluster = jedisCluster;
    }

    @Override
    public Set keys(String pattern) {

        logger.debug("Start getting keys... ");
        TreeSet keys = new TreeSet<>();
        Map clusterNodes =
                jedisCluster.getClusterNodes();

        for (String key : clusterNodes.keySet()) {
            logger.debug("Getting keys from: {}", key);
            JedisPool jedisPool = clusterNodes.get(key);
            Jedis jedisConn = jedisPool.getResource();
            try {
                keys.addAll(jedisConn.keys(pattern));
            } catch (Exception e) {
                logger.error("Getting keys error: {}", e);
            } finally {
                logger.debug("Jedis connection closed");
                jedisConn.close();
            }
        }
        logger.debug("Keys gotten");

        return keys;
    }
}

 

实现思路:

   JedisCluster 可以获取到 cluster 中所有的节点,我们对集群中每个节点都执行 keys(pattern)。

 并对 keys 去重后,返回一个 set 集合。

 

 

此外,我们参考下 spring-redis 的实现,可以验证实现思路 与我们的实现思路一致。

package sunyu.example.bigdata.monitor;

import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class RedisTests {

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Test
    public void t1() {
        stringRedisTemplate.keys()
    }

}

 

/*
 * (non-Javadoc)
 * @see org.springframework.data.redis.connection.RedisKeyCommands#keys(byte[])
*/
@Override
public Set keys(final byte[] pattern) {

    Assert.notNull(pattern, "Pattern must not be null!");

    Collection> keysPerNode = clusterCommandExecutor
        .executeCommandOnAllNodes(new JedisClusterCommandCallback>() {

            @Override
            public Set doInCluster(Jedis client) {
                return client.keys(pattern);
            }
        }).resultsAsList();

    Set keys = new HashSet();
    for (Set keySet : keysPerNode) {
        keys.addAll(keySet);
    }
    return keys;
}

 

 

你可能感兴趣的:(Cache_Redis)