总结redis的连接方式

jedis客户端操作redis主要三种模式:单台模式、分片模式(ShardedJedis)、含有哨兵的分片模式(JedisSentinel)、集群模式(BinaryJedisCluster),分片模式是一种轻量级集群。

1、单台模式:直接通过jedis获取实例就可以

2、分片模式:

JedisPoolConfig config =new JedisPoolConfig();
config.setMinIdle(minIdel);
config.setMaxIdle(intMaxIdel);
config.setMaxTotal(maxSize);
config.setMaxWaitMillis(readTimeOut);
config.setMaxIdle(intMaxIdel);
config.setTestWhileIdle(checkAlive);
ShardedJedisPool sharedPool = new ShardedJedisPool(config,jdsInfoList);‘
sharedPool.getResource();
3、含有哨兵的分片模式

   由于程序连接配置了主服务器的连接,但是此时主服务器挂调,哨兵会将从服务器变成主服务器,但程序是不知道的,出现无法连接异常。Jedis提供了对jedis sentinel pool的封装,所以发生主从切换的时候,web server都不需要重新配置和deploy,对客户端完全透明。高可用性的极佳体现啊。

import org.junit.Test;

import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;

public class TestSentinel {
    @Test
    public void test1() {
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        String masterName = "mymaster";
        Set<String> sentinels = new HashSet<String>();
        sentinels.add("192.168.1.97:26379");
        sentinels.add("192.168.1.96:26379");
        JedisSentinelPool jedisSentinelPool = new JedisSentinelPool(masterName, sentinels, poolConfig);
        HostAndPort currentHostMaster = jedisSentinelPool.getCurrentHostMaster();
        System.out.println(currentHostMaster.getHost()+"--"+currentHostMaster.getPort());//获取主节点的信息
        Jedis resource = jedisSentinelPool.getResource();
        String value = resource.get("a");
        System.out.println(value);//获得键a对应的value值
        resource.close();
    }
}
4、集群模式

import java.util.HashSet;
import java.util.Set;
import org.junit.Test;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPoolConfig;

public class TestCluster {
    @Test
    public void test1() throws Exception {
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        Set<HostAndPort> nodes = new HashSet<HostAndPort>();
        HostAndPort hostAndPort = new HostAndPort("192.168.1.99", 7000);//只给集群里一个实例就可以
        HostAndPort hostAndPort1 = new HostAndPort("192.168.1.99", 7001);
        HostAndPort hostAndPort2 = new HostAndPort("192.168.1.99", 7002);
        HostAndPort hostAndPort3 = new HostAndPort("192.168.1.99", 7003);
        HostAndPort hostAndPort4 = new HostAndPort("192.168.1.99", 7004);
        HostAndPort hostAndPort5 = new HostAndPort("192.168.1.99", 7005);
        nodes.add(hostAndPort);
        nodes.add(hostAndPort1);
        nodes.add(hostAndPort2);
        nodes.add(hostAndPort3);
        nodes.add(hostAndPort4);
        nodes.add(hostAndPort5);
        JedisCluster jedisCluster = new JedisCluster(nodes, poolConfig);//JedisCluster中默认分装好了连接池.
        //redis内部会创建连接池,从连接池中获取连接使用,然后再把连接返回给连接池
        String string = jedisCluster.get("a");
        System.out.println(string);            
    }
}
初始化 代码:

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是个重点,虽然使用的for循环遍历,但是此处的break让此循环立刻跳出
        break;
      } catch (JedisConnectionException e) {
        // try next nodes
      } finally {
        if (jedis != null) {
          jedis.close();
        }
      }
    }

    for (HostAndPort node : startNodes) {
      cache.setNodeIfNotExist(node);
    }
  }
注意上面代码段for循环里面的break: 
它让for循环立刻跳出,导致for循环实际上只执行了一次,也就是说只使用了配置文件中所有节点配置的第一个,如此说来,集群配置文件中节点配置一个和配置多个效果一致。
 
同时还要注意到:通过获取的第一个节点配置实例化了一个Jedis jedis,如果配置文件中第一个节点指向的服务挂机或无法连接,将导致程序无法使用整个集群,虽然redis集群中其它节点是可用的。 

补充:

不管是主从还是分片集群模式注意设置:

config.setTestOnBorrow(false);

config.setTestOnReturn(false);

这样的话在每次发送请求的时候就不用去ping一下服务端是否可用了,降低流量请求,理论上可减少一半

总结连接模板:

主从
// 数据库链接池配置
JedisPoolConfig config = new JedisPoolConfig();
//最大连接数, 应用自己评估,不要超过Redis每个实例最大的连接数
config.setMaxTotal(100);
//最大空闲连接数, 应用自己评估,不要超过Redis每个实例最大的连接数
config.setMaxIdle(50);
config.setMinIdle(20);
config.setMaxWaitMillis(6 * 1000);
config.setTestOnBorrow(false);
config.setTestOnReturn(false);

String host = "*192.168.0.1"; //域名
String password = "please input your password"; //密码
int port = 2222; //端口
int timeout = 3000; //建立连接超时时间
JedisPool pool = new JedisPool(config, host, port, timeout, password);
Jedis jedis = null;
try {
	jedis = pool.getResource();
	/// ... do stuff here ... for example
	jedis.set("foo", "bar");
	String foobar = jedis.get("foo");
	System.out.println(foobar);
	jedis.set("name", "zhangsan");
	System.out.println(jedis.get("name"));
} finally {
	if (jedis != null) {
		jedis.close();
	}
}
/// ... when closing your application:
pool.destroy();
//分片集群
import redis.clients.jedis.*;
import java.util.HashSet;
import java.util.Set;

// 数据库连接池配置
JedisPoolConfig config = new JedisPoolConfig();
//最大连接数, 应用自己评估,不要超过Redis每个实例最大的连接数
config.setMaxTotal(100);
//最大空闲连接数, 应用自己评估,不要超过Redis每个实例最大的连接数
config.setMaxIdle(50);
config.setMinIdle(20);
config.setMaxWaitMillis(6 * 1000);
config.setTestOnBorrow(false);
config.setTestOnReturn(false);

// Redis集群的节点集合
Set<HostAndPort> jedisClusterNodes = new HashSet<HostAndPort>();
jedisClusterNodes.add(new HostAndPort("192.168.0.1", 2222)); //域名 端口
jedisClusterNodes.add(new HostAndPort("192.168.0.2", 3333));
jedisClusterNodes.add(new HostAndPort("192.168.0.3", 4444));

int timeout = 2000; //连接建立超时时间
int maxAttempts = 5; //最多重定向次数
JedisCluster jedisCluster = new JedisCluster(jedisClusterNodes, timeout, maxAttempts, config);

String keyPrefix = "__test";
String value = "";
for (int i=1; i <= 10; i++){
	String key = keyPrefix+i;
	value = "value"+i;
	System.out.println(value);

	// 存数据
	jedisCluster.set(key, value);

	// 取数据
	value= jedisCluster.get(key);
	System.out.println(key + "=" + value);

	//删除数据
	jedisCluster.del(key);

	value = jedisCluster.get(key);
	System.out.println(key + "=" + value);
	System.out.println();
}

版权声明:本文为liyantianmin原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。