主要想说的是,源码中对于jedis连接redis clsuter没有设置密码,所以会一直报错说NOAUTH认证需要

redis集群加密传输 redis集群连接带密码_jedis连接redis

后来,在改篇文章的评论中有如下:

redis集群加密传输 redis集群连接带密码_spring_02

redis集群加密传输 redis集群连接带密码_spring_03


所以进行了jedis2.9.0的版本尝试:

jedis2.9jar包下载:(源码包是跟他放到一起的)

http://www.mvnjar.com/redis.clients/jedis/2.9.0/detail.html

commons-pool2下载(这个不知道具体跟jiedis的版本对应)

http://www.mvnjar.com/org.apache.commons/commons-pool2/jar.html

导入jar包后我就开始做如下操作:

jedisCluster.auth("mima");

直接失败,因为即使是jedis2.9,这个jedisCluster.auth()方法里面也是啥都没有,你可以重写这个方,这个方法内容如下:


/**
   * @deprecated No key operation doesn't make sense for Redis Cluster and Redis Cluster doesn't
   *             support authorization scheduled to be removed on next major release
   */
  @Deprecated
  @Override
  public String auth(String password) {
    throw new JedisClusterException("No way to dispatch this command to Redis Cluster.");
  }


因为连接的是redis集群,所有我就用eclipse看了一下JediCluster的构造方法:

找到了这个new JedisCluster(Set<HostAndPort> jedisClusterNode, int connectionTimeout, int soTimeout,int maxAttempts, String password, final GenericObjectPoolConfig poolConfig);

然后我就修改代码增加上面参数配置项:


package readfile;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPoolConfig;

public class GetData {
	public static void main(String[] args) throws IOException {
		int a = 0;
		JedisPoolConfig i2 = new JedisPoolConfig();
		i2.setMaxTotal(-1);
		i2.setMinIdle(2);
		i2.setMaxIdle(-1);
		i2.setMaxWaitMillis(10000);
		i2.setTestOnBorrow(true);
		i2.setTestOnReturn(true);	
		Set<HostAndPort> nodes = new HashSet<>();
		nodes.add(new HostAndPort("######", 6379));
		nodes.add(new HostAndPort("#####", 6379));
		nodes.add(new HostAndPort("#####", 6379));
		nodes.add(new HostAndPort("####", 6380));
		nodes.add(new HostAndPort("##", 6380));
		nodes.add(new HostAndPort("##", 6380));
		JedisCluster jedis = new JedisCluster(nodes, 10000, 10000, 100, "wkz", i2);		
		 while (a < 10) {
		System.out.println(jedis.get("w"));
		a++;
		 }
		 jedis.close();		
	}		
}


这次顺利的出了结果,证明jedis2.9是好使的,其他验证就没做。


环境介绍:jedis:2.8.0

redis版本:3.2

首先说一下redis集群的方式,一种是cluster的 一种是sentinel的,cluster的是redis 3.0之后出来新的集群方式

本身redis3.2的cluster集群是支持密码的 ,具体怎么搭建,可以查找相关的文档,这里只介绍应用层面的操作

 

jedis2.8.0的版本没有实现对redis cluster集群的密码操作

在jedis中创建redis cluster的对象时,一般是采用

JedisCluster jedisCluster = new JedisCluster(clusterNodes,timeout,jedisPoolConfig);

我们在项目中直接写了一个类专门来负责操作redis的

public           class           RedisClusterUtil {         


                    private           static           final           Logger LOGGER = Logger.getLogger(RedisClusterUtil.          class          );         


                    private           int           timeout =           10000          ;         


                    private           JedisCluster jedisCluster;         


                    private           Set<HostAndPort> clusterNodes ;         


                    


                    public           RedisClusterUtil(String redisUris, JedisPoolConfig jedisPoolConfig)           throws            Exception{         


                    init(redisUris);         


                    checkHostAndPost();         


                    jedisCluster =           new           JedisCluster(clusterNodes,timeout,jedisPoolConfig);         


                    }         


                    


                    /**         


                    * reids 链接节点地址         


                    */         


                    public           void           init(String redisUris) {         


                    LOGGER.info(          "redisUris:"           + redisUris);         


                    // ## 注册redis连接节点         


                    clusterNodes = Sets.newHashSet();         


                    if          (StringUtils.isNotBlank(redisUris)){         


                    // 以“;”分割成"ip:post"         


                    String [] ipAndPostes = redisUris.split(          ";"          );         


                    // 以“:”分割成 “ip”,“post”         


                    if          (ipAndPostes !=           null          ){         


                    for           (String ipAndPost : ipAndPostes){         


                    //ipAndPost 值:(ip:端口)         


                    String [] ipAndPostArray = ipAndPost.split(          ":"          );         


                    clusterNodes.add(          new           HostAndPort(ipAndPostArray[          0          ], Integer.parseInt(ipAndPostArray[          1          ])));         


                    }         


                    }         


                    }         


                    LOGGER.info(          "redis链接节点个数(clusterNodes):"           + clusterNodes.size());         


                    }


  

<?          xml           version="1.0" encoding="UTF-8"?>         


          <          beans           xmlns="http://www.springframework.org/schema/beans"         


                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         


                    xmlns:util="http://www.springframework.org/schema/util"         


                    xsi:schemaLocation="http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd         


                    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd         


                    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd         


                    ">         


                    


                    <          bean           id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">         


                    <          property           name="maxTotal" value="${redis.maxTotal}"/>         


                    <          property           name="maxIdle" value="${redis.maxIdle}"/>         


                    <          property           name="minIdle" value="${redis.minIdle}"/>         


                    <          property           name="maxWaitMillis" value="${redis.maxWaitMillis}"/>         


                    <          property           name="testOnBorrow" value="${redis.testOnBorrow}"/>         


                    </          bean          >         


                    <          bean           id="redisClusterUtil" class="*.*.utils.RedisClusterUtil">         


                    <          constructor-arg           index="0" value="${redisUris}"></          constructor-arg          >         


                    <          constructor-arg           index="1" ref="jedisPoolConfig"></          constructor-arg          >         


                    </          bean          >         


          </          beans          >


jedisCluster之后,看了一下jedisCluster里面有一个jedisCluster.auth("密码")方法,可惜,这个方法里面什么都没有实现,仅仅抛一个异常

@Deprecated
  @Override
  public String auth(String password) {
    throw new JedisClusterException("No way to dispatch this command to Redis Cluster.");
 
  }

所以想通过这个来设置密码是没戏啦,只能去修改jedis的源码啦,我们先直接启动一下看下报错信息,会发现整个jedis在操作cluster集群涉及到的主要的类

redis集群加密传输 redis集群连接带密码_jedis连接redis

这里我们会发现cluster集群最终会调用redis.clients.jedis.JedisClusterConnectionHandler.initializeSlotsCache(Set<HostAndPort>, GenericObjectPoolConfig)方法,而这个方法里面的代码是

 

private           void           initializeSlotsCache(Set<HostAndPort> startNodes, GenericObjectPoolConfig poolConfig) {         


                    for           (HostAndPort hostAndPort : startNodes) {         


                    Jedis jedis =           new           Jedis(hostAndPort.getHost(), hostAndPort.getPort());         


                    try           {         


                    cache.discoverClusterNodesAndSlots(jedis);         


                    break          ;         


                    }           catch           (JedisConnectionException e) {         


                    // try next nodes         


                    }           finally           {         


                    if           (jedis !=           null          ) {         


                    jedis.close();         


                    }         


                    }         


                    }         


                    


                    for           (HostAndPort node : startNodes) {         


                    cache.setNodeIfNotExist(node);         


                    }         


          }


 

  这里我们可以看到代码中有jedis的创建,而jedis本身是可以支持password配置的,这样我们就可以直接写一个方法去给这个类中塞一个密码进去啦

以下是我自己添加的一个方法,主要是添加了密码  <br>          private           void           initializeSlotsCache(Set<HostAndPort> startNodes, GenericObjectPoolConfig poolConfig,String password) {         


                    for           (HostAndPort hostAndPort : startNodes) {         


                    Jedis jedis =           new           Jedis(hostAndPort.getHost(), hostAndPort.getPort());         


                    jedis.auth(password);         


                    try           {         


                    cache.discoverClusterNodesAndSlots(jedis);         


                    break          ;         


                    }           catch           (JedisConnectionException e) {         


                    // try next nodes         


                    }           finally           {         


                    if           (jedis !=           null          ) {         


                    jedis.close();         


                    }         


                    }         


                    }         


                    


                    for           (HostAndPort node : startNodes) {         


                    cache.setNodeIfNotExist(node);         


                    }         


                    }


这样我们就让JedisClusterConnectionHandler支持了密码,再根据上面的异常信息中的信息,分别去新增方法去传递password到JedisClusterConnectionHandler;这里就部再详细介绍每段代码啦,从异常信息中就知道要修改哪些方法啦

 

重写的jedis的代码如上(太长我省略了),重写了jedis的4个类,4个类中分别新增了一个方法,最新项目中调用时,就可以

直接

 

public RedisClusterUtil(String redisUris, JedisPoolConfig jedisPoolConfig) throws  Exception{
        init(redisUris);
        checkHostAndPost();
        jedisCluster = new JedisCluster(clusterNodes,timeout,jedisPoolConfig,"密码");
 
    }

 

这样就结束啦

public class RedisClusterUtil {    private static final Logger LOGGER = Logger.getLogger(RedisClusterUtil.class);    private int timeout = 10000;    private JedisCluster jedisCluster;    private Set<HostAndPort> clusterNodes ;


 

public RedisClusterUtil(String redisUris, JedisPoolConfig jedisPoolConfig) throws  Exception{        init(redisUris);        checkHostAndPost();        jedisCluster = new JedisCluster(clusterNodes,timeout,jedisPoolConfig,"!QAZ2wsx");    }        /**     * reids 链接节点地址     */    public void init(String redisUris) {        LOGGER.info("redisUris:" + redisUris);        // ## 注册redis连接节点        clusterNodes = Sets.newHashSet();        if(StringUtils.isNotBlank(redisUris)){            // 以“;”分割成"ip:post"            String [] ipAndPostes = redisUris.split(";");            // 以“:”分割成 “ip”,“post”            if(ipAndPostes != null){                for (String ipAndPost : ipAndPostes){                    //ipAndPost 值:(ip:端口)                    String [] ipAndPostArray = ipAndPost.split(":");                    clusterNodes.add(new HostAndPort(ipAndPostArray[0], Integer.parseInt(ipAndPostArray[1])));                }            }        }        LOGGER.info("redis链接节点个数(clusterNodes):" + clusterNodes.size());    }