# 这是Java的Redis客户端工具类 - 2016/12/15 caisz
## 该模块包含2个主要文件:
包路径 com.keydak.utils.redis
- 命令接口声明 IRedisUtils : 声明给外界使用的工具类接口
- 抽象工具类 AbstractRedisUtils : 统一的工具类实现模板
## java Redis客户端拥有2类常用的实现方案:
- 采用jedis连接池直连redis单机服务器
- 采用jedis连接redis服务器集群
### redis服务器集群方案截止于目前有3种方案:
- 采用客户端shared切片访问相互独立的redis服务器集群,该方案存在数据同步问题。
- 采用服务器同步集群,客户端直连集群的Master,Master从slave选举获得,相关技术有官方的推出的redis cluster,暂时不适合生产环境,以及 社区的Redis Sentinel哨兵,哨兵较多人使用 。
- 采用redis集群的代理中间件如:Twemproxy,以及 豌豆荚的Codis
### 本模块中 com.keydak.utils.redis.impl.JedisPoolRedisUtils 采用jedis连接池直连redis单机服务器,其他方案需要另外实现。
* jedis本身不具备线程安全和连接池管理功能,使用JedisPool实现jedis客户端操作,
* 采用JedisPool使得redis具备有线程安全特性,同时减少连接的重复创建次数。
package com.keydak.utils.redis;
/**
* Redis命令接口
* Created by Caisz on 2016/12/14.
*/
public interface IRedisUtils {
/**
* RedisUtils 的析构函数,负责在回收对象时关闭资源,如:连接池对象等等
*/
public void destroy();
/**
* redis ping命令
* @return
*/
public String ping();
/**
* redis set命令
* @param key
* @param value
* @return
*/
public Object set( String key,String value );
/**
* redis get命令
* @param key
* @return
*/
public Object get( String key );
}
package com.keydak.utils.redis;
import redis.clients.jedis.Jedis;
/**
* 抽象的RedisUtils
*
* 实现finalize(),确保在JVM出发‘垃圾回收机制’的时候,销毁系统资源。
* 提供获取Jedis客户端的抽象方法
* 提供初始化工具类的抽象方法
*
* Created by Caisz on 2016/12/14.
*/
public abstract class AbstractRedisUtils implements IRedisUtils {
/**
* 获取jedis客户端
* @return
*/
protected abstract Jedis getJedis();
/**
* 初始化构造方法的时候调用
*/
protected abstract void init() throws Exception;
protected void finalize() throws java.lang.Throwable {
// 递归调用超类中的finalize方法
destroy();
super.finalize();
}
}
package com.keydak.utils.redis.impl;
import com.keydak.utils.redis.AbstractRedisUtils;
import com.keydak.utils.redis.IRedisUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/**
* Redis命令工具类
*
* jedis本身不具备线程安全和连接池管理功能,使用JedisPool实现jedis客户端操作,
* 采用JedisPool使得redis具备有线程安全特性,同时减少连接的重复创建次数。
*
* Created by Caisz on 2016/12/15.
*/
public class JedisPoolRedisUtils extends AbstractRedisUtils implements IRedisUtils {
// 如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。
private static final int CONSTANT_MAX_TOTAL = 500;
// 控制一个pool最多有多少个状态为idle(空闲的)的jedis实例。
private static final int CONSTANT_MAX_IDLE = 5;
// 表示当borrow(引入)一个jedis实例时,最大的等待时间,如果超过等待时间,则直接抛出JedisConnectionException;
private static final long CONSTANT_MAX_WAIT_MILLIS = 1000*100 ;
// 在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;
private static final boolean CONSTANT_TEST_ON_BORROW = true;
// redis服务器 Ip + 端口
private static final String CONSTANT_REDIS_SERVER_IP = "localhost";
private static final int CONSTANT_REDIS_SERVER_PORT = 6379;
private JedisPool pool = null;
public JedisPoolRedisUtils() {
try{
// 初始化连接池
init();
} catch ( Exception e ) {
System.out.println( e.getMessage() );
}
}
/**
* 受保护的Jedis客户端获取方法
* @return
*/
@Override
protected Jedis getJedis() {
try{
// 同步初始化Redis连接池
if( pool == null ) {
synchronized (JedisPoolRedisUtils.class) {
if( pool == null ) {
init();
}
}
}
// 返回jedis客户端
return pool.getResource();
} catch ( Exception e ) {
System.out.println( "pool Connection inited is Exception ! -- " + e.getMessage() );
}
return null;
}
/**
* 初始化连接池
* @throws Exception
*/
@Override
protected void init() throws Exception {
JedisPoolConfig config = new JedisPoolConfig();
//控制一个pool可分配多少个jedis实例,通过pool.getResource()来获取;
config.setMaxTotal( CONSTANT_MAX_TOTAL );
config.setMaxIdle( CONSTANT_MAX_IDLE );
config.setMaxWaitMillis( CONSTANT_MAX_WAIT_MILLIS );
config.setTestOnBorrow( CONSTANT_TEST_ON_BORROW );
pool = new JedisPool(config, CONSTANT_REDIS_SERVER_IP, CONSTANT_REDIS_SERVER_PORT);
System.out.println( "RedisUtils had inited!");
}
/**
* 线程安全的连接池销毁方法,可以在异常处理时调用销毁连接池,或者等待 ‘JVM垃圾回收’ 的时候延迟销毁。
*/
@Override
public void destroy() {
System.out.println( "RedisUtils had finalized!");
try {
// 同步销毁连接池
if( pool != null ) {
synchronized (JedisPoolRedisUtils.class) {
if( pool != null ) {
pool.close();
}
}
}
} catch ( Exception e ) {
System.out.println( "pool closed throw exception! --- " + e.getMessage() );
}
}
@Override
public String ping() {
Jedis jedis = null;
try{
jedis = this.getJedis();
if( jedis != null ) {
return jedis.ping();
}
}
finally {
if( jedis != null ) jedis.close();
}
return null;
}
@Override
public String set(String key, String value) {
Jedis jedis = null;
try{
jedis = this.getJedis();
if( jedis != null ) {
return jedis.set( key, value );
}
}
finally {
if( jedis != null ) jedis.close();
}
return null;
}
@Override
public Object get(String key) {
Jedis jedis = null;
try{
jedis = this.getJedis();
if( jedis != null ) {
return jedis.get(key);
}
}
finally {
if( jedis != null ) jedis.close();
}
return null;
}
/**
* 使用示例
* @param args
*/
public static void main(String[] args) {
IRedisUtils redisUtils = null;
try{
// 获取Redis工具类
redisUtils = new JedisPoolRedisUtils();
// 测试Ping命令
System.out.println( "Server is running: " + redisUtils.ping() );
// 测试set、get命令
redisUtils.set( "myname", "假猪套天下第一!" );
System.out.println( "myname : " + redisUtils.get( "myname" ) );
}
finally {
// 即时关闭连接资源,如果不调用destroy(),直到垃圾回收才被回收。
if( redisUtils != null ) { redisUtils.destroy(); }
}
}
}