redis的Java客户端jedis池的介绍及使用

redis的Java客户端jedis池的介绍及使用

转自:http://blog.csdn.net/unix21/article/details/51354823

需要commons-pool.jar、jedis-2.1.0.jar

<dependency>
<groupId>commons-pool</groupId>
<artifactId>commons-pool</artifactId>
<version>1.6</version>
</dependency>

<dependency>  
   <groupId>redis.clients</groupId>  
   <artifactId>jedis</artifactId>  
   <version>2.1.0</version>  
</dependency>

其实这个是引用自网友http://blog.csdn.net/tuposky/article/details/45340183,有2个版本,差别就是ReentrantLock和synchronized。另外原作者使用了断言,我觉得这个还是不用为好。


ReentrantLock版

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. import java.util.concurrent.locks.ReentrantLock;  
  2. import org.apache.commons.lang.StringUtils;  
  3. import org.apache.log4j.Logger;  
  4. import redis.clients.jedis.Jedis;  
  5. import redis.clients.jedis.JedisPool;  
  6. import redis.clients.jedis.JedisPoolConfig;  
  7.   
  8. /** 
  9.  * Redis 工具类 
  10.  */  
  11. public class JedisUtil {  
  12.   
  13.     protected static ReentrantLock lockPool = new ReentrantLock();  
  14.     protected static ReentrantLock lockJedis = new ReentrantLock();  
  15.   
  16.     protected static Logger logger = Logger.getLogger(JedisUtil.class);  
  17.   
  18.     //Redis服务器IP  
  19.     private static String ADDR_ARRAY = "xxx.xxx.xxx.xxx";  
  20.   
  21.     //Redis的端口号  
  22.     private static int PORT = 6379;  
  23.   
  24.     //访问密码  
  25.     private static String AUTH = "http://blog.csdn.net/unix21";  
  26.     //可用连接实例的最大数目,默认值为8;  
  27.     //如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。  
  28.     private static int MAX_ACTIVE = 8;  
  29.   
  30.     //控制一个pool最多有多少个状态为idle(空闲的)的jedis实例,默认值也是8。  
  31.     private static int MAX_IDLE = 8;  
  32.   
  33.     //等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException;  
  34.     private static int MAX_WAIT = 3000;  
  35.   
  36.     //超时时间  
  37.     private static int TIMEOUT = 10000;  
  38.   
  39.     //在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;  
  40.     private static boolean TEST_ON_BORROW = false;  
  41.   
  42.     private static JedisPool jedisPool = null;  
  43.   
  44.     /** 
  45.      * redis过期时间,以秒为单位 
  46.      */  
  47.     public final static int EXRP_HOUR = 60 * 60;            //一小时  
  48.     public final static int EXRP_DAY = 60 * 60 * 24;        //一天  
  49.     public final static int EXRP_MONTH = 60 * 60 * 24 * 30//一个月  
  50.   
  51.     /** 
  52.      * 初始化Redis连接池 
  53.      */  
  54.     private static void initialPool() {  
  55.         try {  
  56.             JedisPoolConfig config = new JedisPoolConfig();  
  57.             config.setMaxTotal(MAX_ACTIVE);  
  58.             config.setMaxIdle(MAX_IDLE);  
  59.             config.setMaxWaitMillis(MAX_WAIT);  
  60.             config.setTestOnBorrow(TEST_ON_BORROW);  
  61.             jedisPool = new JedisPool(config, ADDR_ARRAY.split(",")[0], PORT, TIMEOUT, AUTH);  
  62.         } catch (Exception e) {  
  63.             logger.error("First create JedisPool error : " + e);  
  64.             try {  
  65.                 //如果第一个IP异常,则访问第二个IP  
  66.                 JedisPoolConfig config = new JedisPoolConfig();  
  67.                 config.setMaxTotal(MAX_ACTIVE);  
  68.                 config.setMaxIdle(MAX_IDLE);  
  69.                 config.setMaxWaitMillis(MAX_WAIT);  
  70.                 config.setTestOnBorrow(TEST_ON_BORROW);  
  71.                 jedisPool = new JedisPool(config, ADDR_ARRAY.split(",")[1], PORT, TIMEOUT, AUTH);  
  72.             } catch (Exception e2) {  
  73.                 logger.error("Second create JedisPool error : " + e2);  
  74.             }  
  75.         }  
  76.     }  
  77.   
  78.     /** 
  79.      * 在多线程环境同步初始化 
  80.      */  
  81.     private static void poolInit() {  
  82.         lockPool.lock();  
  83.         try {  
  84.             if (jedisPool == null) {  
  85.                 initialPool();  
  86.             }  
  87.         } catch (Exception e) {  
  88.             e.printStackTrace();  
  89.         } finally {  
  90.             lockPool.unlock();  
  91.         }  
  92.     }  
  93.   
  94.     public static Jedis getJedis() {  
  95.         lockJedis.lock();  
  96.         if (jedisPool == null) {  
  97.             poolInit();  
  98.         }  
  99.         Jedis jedis = null;  
  100.         try {  
  101.             if (jedisPool != null) {  
  102.                 jedis = jedisPool.getResource();  
  103.             }  
  104.         } catch (Exception e) {  
  105.             logger.error("Get jedis error : " + e);  
  106.         } finally {  
  107.             returnResource(jedis);  
  108.             lockJedis.unlock();  
  109.         }  
  110.         return jedis;  
  111.     }  
  112.   
  113.     /** 
  114.      * 释放jedis资源 
  115.      * 
  116.      * @param jedis 
  117.      */  
  118.     public static void returnResource(final Jedis jedis) {  
  119.         if (jedis != null && jedisPool != null) {  
  120.             jedisPool.returnResource(jedis);  
  121.         }  
  122.     }  
  123.   
  124.     /** 
  125.      * 设置 String 
  126.      * 
  127.      * @param key 
  128.      * @param value 
  129.      */  
  130.     public synchronized static void setString(String key, String value) {  
  131.         try {  
  132.             value = StringUtils.isEmpty(value) ? "" : value;  
  133.             getJedis().set(key, value);  
  134.         } catch (Exception e) {  
  135.             logger.error("Set key error : " + e);  
  136.         }  
  137.     }  
  138.   
  139.     /** 
  140.      * 设置 过期时间 
  141.      * 
  142.      * @param key 
  143.      * @param seconds 以秒为单位 
  144.      * @param value 
  145.      */  
  146.     public synchronized static void setString(String key, int seconds, String value) {  
  147.         try {  
  148.             value = StringUtils.isEmpty(value) ? "" : value;  
  149.             getJedis().setex(key, seconds, value);  
  150.         } catch (Exception e) {  
  151.             logger.error("Set keyex error : " + e);  
  152.         }  
  153.     }  
  154.   
  155.     /** 
  156.      * 获取String值 
  157.      * 
  158.      * @param key 
  159.      * @return value 
  160.      */  
  161.     public synchronized static String getString(String key) {  
  162.         if (getJedis() == null || !getJedis().exists(key)) {  
  163.             return null;  
  164.         }  
  165.         return getJedis().get(key);  
  166.     }  
  167. }  


synchronized版
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. import java.util.concurrent.locks.ReentrantLock;  
  2. import org.apache.commons.lang.StringUtils;  
  3. import org.apache.log4j.Logger;  
  4. import redis.clients.jedis.Jedis;  
  5. import redis.clients.jedis.JedisPool;  
  6. import redis.clients.jedis.JedisPoolConfig;  
  7.   
  8. /** 
  9.  * Redis 工具类 
  10.  */  
  11. public class JedisUtil {  
  12.   
  13.     protected static ReentrantLock lockPool = new ReentrantLock();  
  14.     protected static ReentrantLock lockJedis = new ReentrantLock();  
  15.   
  16.     protected static Logger logger = Logger.getLogger(JedisUtil.class);  
  17.   
  18.     //Redis服务器IP  
  19.     private static String ADDR_ARRAY = "xxx.xxx.xxx.xxx";  
  20.   
  21.     //Redis的端口号  
  22.     private static int PORT = 6379;  
  23.   
  24.     //访问密码  
  25.     private static String AUTH = "http://blog.csdn.net/unix21";  
  26.     //可用连接实例的最大数目,默认值为8;  
  27.     //如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。  
  28.     private static int MAX_ACTIVE = 8;  
  29.   
  30.     //控制一个pool最多有多少个状态为idle(空闲的)的jedis实例,默认值也是8。  
  31.     private static int MAX_IDLE = 8;  
  32.   
  33.     //等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException;  
  34.     private static int MAX_WAIT = 3000;  
  35.   
  36.     //超时时间  
  37.     private static int TIMEOUT = 10000;  
  38.   
  39.     //在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;  
  40.     private static boolean TEST_ON_BORROW = false;  
  41.   
  42.     private static JedisPool jedisPool = null;  
  43.   
  44.     /** 
  45.      * redis过期时间,以秒为单位 
  46.      */  
  47.     public final static int EXRP_HOUR = 60 * 60;            //一小时  
  48.     public final static int EXRP_DAY = 60 * 60 * 24;        //一天  
  49.     public final static int EXRP_MONTH = 60 * 60 * 24 * 30//一个月  
  50.   
  51.     /** 
  52.      * 初始化Redis连接池 
  53.      */  
  54.     private static void initialPool() {  
  55.         try {  
  56.             JedisPoolConfig config = new JedisPoolConfig();  
  57.             config.setMaxTotal(MAX_ACTIVE);  
  58.             config.setMaxIdle(MAX_IDLE);  
  59.             config.setMaxWaitMillis(MAX_WAIT);  
  60.             config.setTestOnBorrow(TEST_ON_BORROW);  
  61.             jedisPool = new JedisPool(config, ADDR_ARRAY.split(",")[0], PORT, TIMEOUT, AUTH);  
  62.         } catch (Exception e) {  
  63.             logger.error("First create JedisPool error : " + e);  
  64.             try {  
  65.                 //如果第一个IP异常,则访问第二个IP  
  66.                 JedisPoolConfig config = new JedisPoolConfig();  
  67.                 config.setMaxTotal(MAX_ACTIVE);  
  68.                 config.setMaxIdle(MAX_IDLE);  
  69.                 config.setMaxWaitMillis(MAX_WAIT);  
  70.                 config.setTestOnBorrow(TEST_ON_BORROW);  
  71.                 jedisPool = new JedisPool(config, ADDR_ARRAY.split(",")[1], PORT, TIMEOUT, AUTH);  
  72.             } catch (Exception e2) {  
  73.                 logger.error("Second create JedisPool error : " + e2);  
  74.             }  
  75.         }  
  76.     }  
  77.   
  78.     /** 
  79.      * 在多线程环境同步初始化 
  80.      */  
  81.     private static synchronized void poolInit() {  
  82.         if (jedisPool == null) {    
  83.             initialPool();  
  84.         }  
  85.     }  
  86.   
  87.       
  88.     /** 
  89.      * 同步获取Jedis实例 
  90.      * @return Jedis 
  91.      */  
  92.     public synchronized static Jedis getJedis() {    
  93.         if (jedisPool == null) {    
  94.             poolInit();  
  95.         }  
  96.         Jedis jedis = null;  
  97.         try {    
  98.             if (jedisPool != null) {    
  99.                 jedis = jedisPool.getResource();   
  100.             }  
  101.         } catch (Exception e) {    
  102.             logger.error("Get jedis error : "+e);  
  103.         }finally{  
  104.             returnResource(jedis);  
  105.         }  
  106.         return jedis;  
  107.     }    
  108.   
  109.     /** 
  110.      * 释放jedis资源 
  111.      * 
  112.      * @param jedis 
  113.      */  
  114.     public static void returnResource(final Jedis jedis) {  
  115.         if (jedis != null && jedisPool != null) {  
  116.             jedisPool.returnResource(jedis);  
  117.         }  
  118.     }  
  119.   
  120.     /** 
  121.      * 设置 String 
  122.      * 
  123.      * @param key 
  124.      * @param value 
  125.      */  
  126.     public synchronized static void setString(String key, String value) {  
  127.         try {  
  128.             value = StringUtils.isEmpty(value) ? "" : value;  
  129.             getJedis().set(key, value);  
  130.         } catch (Exception e) {  
  131.             logger.error("Set key error : " + e);  
  132.         }  
  133.     }  
  134.   
  135.     /** 
  136.      * 设置 过期时间 
  137.      * 
  138.      * @param key 
  139.      * @param seconds 以秒为单位 
  140.      * @param value 
  141.      */  
  142.     public synchronized static void setString(String key, int seconds, String value) {  
  143.         try {  
  144.             value = StringUtils.isEmpty(value) ? "" : value;  
  145.             getJedis().setex(key, seconds, value);  
  146.         } catch (Exception e) {  
  147.             logger.error("Set keyex error : " + e);  
  148.         }  
  149.     }  
  150.   
  151.     /** 
  152.      * 获取String值 
  153.      * 
  154.      * @param key 
  155.      * @return value 
  156.      */  
  157.     public synchronized static String getString(String key) {  
  158.         if (getJedis() == null || !getJedis().exists(key)) {  
  159.             return null;  
  160.         }  
  161.         return getJedis().get(key);  
  162.     }  
  163. }  


多线程

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class ClientThread extends Thread {  
  2.   
  3.     int i = 0;  
  4.   
  5.     public ClientThread(int i) {  
  6.         this.i = i;  
  7.     }  
  8.   
  9.     public void run() {  
  10.         Date date = new Date();  
  11.         DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  12.         String time = format.format(date);  
  13.         JedisUtil.setString("foo", time);  
  14.         String foo = JedisUtil.getString("foo");        
  15.         System.out.println("【输出>>>>】foo:" + foo + " 第:"+i+"个线程" +"当前时间:"+DateUtil.getNowTimeString());  
  16.     }  
  17. }  

起10000个线程

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public static void main(String[] args) {                
  2.         for (int i = 0; i < 10000; i++) {            
  3.             ClientThread t = new ClientThread(i);  
  4.             t.start();  
  5.         }  
  6.     }  


运行非常稳定:

在单机4核普通PC机器测试下来10000条数据跑了2秒,性能还是不错的,没有报异常。


下面是一个处理不好的情况,就会报出种种异常,这种连接池一定要用多线程测试,不然线下没事,线上就会时不时的出问题:


  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值