背景
分布式缓存连接池版Java客户端,在redis官方java客户端Jedis的基础上进行了封装,针对分布式缓存存在多个接入机的模式,建立并维护与多接入机的连接池(同步连接),支持:
(1)多接入机模式下的连接池操作,可配置多接入机地址,采用轮询方式发送命令至接入机集群。 
(2)完全兼容jedis,可直接使用官方客户端Jedis的操作。
(3)客户端可动态监测服务端可用状态来调整获取连接策略。
(4)支持最大连接数、最大/最小空闲连接数、监测开闭、后台监测周期等多项参数的配置。
通过全国各省IT推广的运维经验,建议单个应用使用单个连接池,而不是单个应用使用多个连接池(会导致总体连接数较高,浪费资源)。
开发相关配置
-  项目配置
- Maven-pom配置
 注意:2.3.2版本以后,Java连接池版客户端依赖ctg-cache-nclient,不再依赖ctg-cache-control,新版的nclient中jedis请使用3.3.0。<dependency> <groupId>com.ctg.itrdc.cache</groupId> <artifactId>ctg-cache-nclient</artifactId> <version>2.8.4</version> </dependency><distributionManagement> <repository> <id>releases</id> <name>Internal Releases</name> <url>http://10.142.90.61:8081/nexus/content/repositories/releases</url> </repository> <snapshotRepository> <id>snapshots</id> <name>Internal Snapshots</name> <url>http://10.142.90.61:8081/nexus/content/repositories/snapshots</url> </snapshotRepository> </distributionManagement> 
- 配置项
需要设置如下两个配置类,其中后者是前者的变量。 CtgJedisPoolConfig 包含客户端所有配置项 参数 类型 说明 poolConfig GenericObjectPoolConfig Apache pool 配置,默认为JedisPoolConfig connectionTimeout int 连接超时时间,单位毫秒,默认5秒 soTimeout int 操作超时时间,单位毫秒,默认5秒 password String 密码,必填,格式为“用户#密码” database Int/String 桶位或者分组名,必填 clientName String 客户端名,默认null period long 后台监控执行周期,毫秒,默认3秒 monitorTimeout int 监控命令超时时间,毫秒,默认500毫秒 monitorErrorNum int 监控连续出错几次,将接入机节点判断为失效,默认3次 nodes List<HostAndPort> 接入机地址列表 monitorLog boolean 是否开启后台监控日志,默认开启 GenericObjectPoolConfig 封装了与连接池有关配置 参数 类型 说明 MaxTotal int 最大连接数(空闲+使用中),建议设置为应用线程数的一半到应用的线程总数的范围内。 MaxIdle int 最大空闲连接数,不超过最大连接数 MinIdle int 保持的最小空闲连接数,默认0 MaxWaitMillis long 获取连接时的最大等待毫秒数,如果超时就抛异常, 小于零:阻塞不确定的时间, 默认-1 TestWhileIdle boolean 在空闲时检查有效性,默认true MinEvictableIdleTimeMillis long 逐出连接的最小空闲时间(毫秒),默认60秒 TimeBetweenEvictionRunsMillis long 逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认30秒 NumTestsPerEvictionRun int 每次逐出检查时 逐出的最大数目百分比,如果是负数,则为1/abs(n),默认为-1 
- 配置操作连接池对象的实例化需要CtgJedisPoolConfig配置类,CtgJedisPoolConfig配置类中的参数可参考上述表格,其中(GenericObjectPoolConfig)poolConfig变量用于配置客户端与接入机的连接池参数,类JedisPoolConfig继承自GenericObjectPoolConfig并设置了合理的默认参数。所以在配置操作时,CtgJedisPoolConfig中的poolConfig参数推荐使用类JedisPoolConfig实现,并设置额外的配置。参考代码如下:
List<HostAndPort> hostAndPortList = new ArrayList(); // 接入机的ip和端口号 HostAndPort host1 = new HostAndPort("132.122.232.225" ,8352); HostAndPort host2 = new HostAndPort("132.122.232.225" ,8362 ); hostAndPortList.add(host1); hostAndPortList.add(host2); GenericObjectPoolConfig poolConfig = new JedisPoolConfig(); poolConfig.setMaxTotal(10); //最大连接数(空闲+使用中),建议设置为应用线程数的一半到应用的线程总数的范围内。 poolConfig.setMaxIdle(10); //最大空闲连接数 poolConfig.setMinIdle(3); //保持的最小空闲连接数 poolConfig.setMaxWaitMillis(3000); CtgJedisPoolConfig config = new CtgJedisPoolConfig(hostAndPortList); config.setDatabase(255)//分组名或者db .setPassword("pool#Jedis*123") // 实例名#密码 .setPoolConfig(poolConfig) .setPeriod(3000) .setMonitorTimeout(200);
 
- Maven-pom配置
- 连接池操作
- 创建连接池CtgJedisPool
 入参说明:CtgJedisPool pool = new CtgJedisPool(config);
 示例参数 类型 是否可为空 说明 config CtgJedisPoolConfig N 连接池配置数据 List<HostAndPort> hostAndPortList = new ArrayList(); HostAndPort host1 = new HostAndPort("132.122.232.225" ,8352); HostAndPort host2 = new HostAndPort("132.122.232.225" ,8362 ); hostAndPortList.add(host1); hostAndPortList.add(host2); GenericObjectPoolConfig poolConfig = new JedisPoolConfig(); poolConfig.setMaxTotal(10); // 最大连接数(空闲+使用中) poolConfig.setMaxIdle(5); //最大空闲连接数 poolConfig.setMinIdle(3); //保持的最小空闲连接数 poolConfig.setMaxWaitMillis(3000); CtgJedisPoolConfig config = new CtgJedisPoolConfig(hostAndPortList); config.setDatabase(255).setPassword("pool#Jedis*123").setPoolConfig(poolConfig) .setPeriod(3000).setMonitorTimeout(200); CtgJedisPool pool = new CtgJedisPool(config); 
- 
销毁连接池close (CtgJedisPool)pool.close();功能描述:销毁连接池,可能会抛出运行时异常: 
 示例throw new JedisException("Could not destroy the pool", e);CtgJedisPool pool = new CtgJedisPool(config); pool.close(); 
- 获取连接getResource
(CtgJedisPool)pool.getResource();功能描述:从连接池中获取一个可用连接,客户端会轮询可用列表从中拿出可用连接,使用完成后请使用归还命令归还连接。 注意事项:获取失败会抛出异常CtgJedisPoolException 返回类型:ProxyJedis示例 initPool(); ProxyJedis jedis = new ProxyJedis(); try { jedis = pool.getResource(); String key = StringGenarator.getRandomKeyString(10); String value = StringGenarator.getRandomValueString(10); //sendCommand 可能会抛出 运行时异常 jedis.set(key, value); //sendCommand 可能会抛出 运行时异常 jedis.get(key); jedis.close(); } catch (Throwable je){ jedis.close(); } pool.close(); 
- 归还连接jedis.close()
 功能描述:将连接归还至连接池中,如果使用过程发生异常、超时,将会销毁该连接(ProxyJedis)jedis.close();示例 initPool(); ProxyJedis jedis = new ProxyJedis(); try { jedis = pool.getResource(); String key = StringGenarator.getRandomKeyString(10); String value = StringGenarator.getRandomValueString(10); //sendCommand 可能会抛出 运行时异常 jedis.set(key, value); //sendCommand 可能会抛出 运行时异常 jedis.get(key); jedis.close(); } catch (Throwable je){ jedis.close(); } pool.close(); 
 
- 创建连接池CtgJedisPool
- 其他说明
(1)密码与桶位在初始化连接池时使用,后期不可修改。 (2)获取连接后及时归还连接,使用过程中发生异常catch后要归还连接。 (3)GenericObjectPoolConfig配置的连接池数量是与所有接入机连接数之和,请参考Apache Commons pool2合理配置。 (4)类JedisPoolConfig继承自GenericObjectPoolConfig并设置了合理的默认参数,推荐使用JedisPoolConfig作为配置。 (5)查问题时请先跟踪连接池客户端的监控日志,判断接入机状况; (6)单个连接只能单线程调用,不可多线程复用。 
- 示例代码
public class CtgJedisPoolTest { public static final Logger logger = LoggerFactory.getLogger(CtgJedisPoolTest.class); public static void main(String[] args) { BasicConfigurator.configure(); List<HostAndPort> hostAndPortList = new ArrayList(); //接入机地址列表 HostAndPort host1 = new HostAndPort("132.122.232.225" ,8352); //接入机-1 HostAndPort host2 = new HostAndPort("132.122.232.225" ,8362); //接入机-2 hostAndPortList.add(host1); hostAndPortList.add(host2); GenericObjectPoolConfig poolConfig = new JedisPoolConfig(); //线程池配置 poolConfig.setMaxTotal(10); // 最大连接数(空闲+使用中) poolConfig.setMaxIdle(3); //最大空闲连接数 poolConfig.setMinIdle(3); //保持的最小空闲连接数 poolConfig.setMaxWaitMillis(3000); //借出连接时最大的等待时间 CtgJedisPoolConfig config = new CtgJedisPoolConfig(hostAndPortList); config.setDatabase(255) //分组对应的桶位 .setPassword("pool#Jedis*123") // “用户#密码” .setPoolConfig(poolConfig) //线程池配置 .setPeriod(3000) //后台监控执行周期,毫秒 .setMonitorTimeout(200); //后台监控ping命令超时时间,毫秒 CtgJedisPool pool = new CtgJedisPool(config); //创建连接池 ProxyJedis jedis = null; for (int i = 1; i <= 1000; i++) { try { jedis = pool.getResource(); //获取连接,可能抛出异常 String key = "**key" +i; String value = "**value" + i; jedis.set(key, value); } catch (CtgJedisPoolException e) { logger.error(e.getMessage(), e); } catch (JedisConnectionException e) { logger.error(e.getMessage(), e); } finally { // finally内执行,确保连接归还 try{ jedis.close(); } catch (Throwable e) { } //归还连接至连接池 } } pool.close(); //关闭连接池 } }