为什么要用Jedis连接池+浅谈jedis连接池使用
为什么要使用Jedis连接池
View Code
View Code
Redis作为缓存数据库理论上和MySQL一样需要客户端和服务端建立起来连接进行相关操作,使用MySQL的时候相信大家都会使用一款开源的连接池,例如C3P0.因为直连会消耗大量的数据库资源,每一次新建一个连接之,使用后再断开连接,对于频繁访问的场景,这显然不是高效的。
生产环境一般使用连接池的方式对Redis连接进行管理,所有Jedis对象先放在池子中每一次需要的时候连接Redis,只需要在池子中借,用完了再归还给池子。
Jedis提供了JedisPool这个类作为对Jedis的连接池。使用如下:客户端连接Redis使用的是TCP协议,直连的方式每次需要建立TCP连接,而连接池的方式是可以预先初始化好Jedis连接,所以每次只需要从Jedis连接池借用即可,而借用和归还操作是在本地进行的,只有少量的并发同步开销,远远小于新建TCP连接的开销。另外直连的方式无法限制Jedis对象的个数,在极端情况下可能会造成连接泄露,而连接池的形式可以有效的保护和控制资源的使用。但是直连的方式也并不是一无是处,下面给出两种方式各自的优劣势。
1 public class RedisPool { 2 //声明成static的原因:保证jedis连接池在tomcat启动时就加载出来 3 //jedis连接池 4 private static JedisPool pool; 5 //与redis连接池连接的最大连接数 6 private static Integer maxTotal = Integer.parseInt(PropertiesUtil.getProperty("redis.max.total", "20")); 7 //在这个连接池中最多有多少个状态为idle的jedis实例,jedis连接池里就是jedis的实例,idle就是空闲的jedis实例 8 //在jedis连接池中最大的idle状态(空闲的)的jedis实例的个数 9 private static Integer maxIdle = Integer.parseInt(PropertiesUtil.getProperty("redis.max.idle", "10")); 10 //在jedis连接池中最小的idle状态(空闲的)的jedis实例的个数 11 private static Integer minIdle = Integer.parseInt(PropertiesUtil.getProperty("redis.min.idle", "2")); 12 13 //在borrow一个jedis实例的时候,是否要进行验证操作,如果赋值为true,则得到的jedis实例肯定是可用的 14 private static Boolean testOnBorrow = Boolean.parseBoolean(PropertiesUtil.getProperty("redis.test.borrow", "true")); 15 //在return一个jedis实例的时候,是否要进行验证操作,如果赋值为true,则返回jedis连接池的jedis实例肯定是可用的 16 private static Boolean testOnReturn = Boolean.parseBoolean(PropertiesUtil.getProperty("redis.test.return", "true")); 17 18 private static String redisIp = PropertiesUtil.getProperty("redis.ip"); 19 private static Integer redisPort = Integer.parseInt(PropertiesUtil.getProperty("redis.port")); 20 21 //初始化连接池,只会调用一次 22 private static void initPool() { 23 JedisPoolConfig config = new JedisPoolConfig(); 24 25 config.setMaxTotal(maxTotal); 26 config.setMaxIdle(maxIdle); 27 config.setMinIdle(minIdle); 28 29 config.setTestOnBorrow(testOnBorrow); 30 config.setTestOnReturn(testOnReturn); 31 32 //连接池耗尽的时候,是否阻塞,false会抛出异常,true阻塞直到超时,会抛出超时异常,默认为true 33 config.setBlockWhenExhausted(true); 34 35 //这里超时时间是2s 36 pool = new JedisPool(config, redisIp, redisPort, 1000*2); 37 38 } 39 40 static { 41 initPool(); 42 } 43 44 //从连接池中拿取一个实例 45 public static Jedis getJedis() { 46 return pool.getResource(); 47 } 48 49 //将正常实例放回jedis连接池 50 public static void returnResource(Jedis jedis) { 51 pool.returnResource(jedis); 52 } 53 54 //将破损实例放回jedis连接池 55 public static void returnBrokenResource(Jedis jedis) { 56 pool.returnResource(jedis); 57 } 58 59 }
JedisPoolUtil向外提供的工具类如下所示:
1 public class RedisPoolUtil { 2 3 //重新设置有效期 4 //参数只有key和有效期,因为只需要根据key设置有效期即可 5 public static Long expire(String key, int exTime) { 6 Jedis jedis = null; 7 Long result = null; 8 try { 9 jedis = RedisPool.getJedis(); 10 //设置有效期 11 result = jedis.expire(key, exTime); 12 } catch (Exception e) { 13 log.error("setex key:{} error", key, e); 14 RedisPool.returnBrokenResource(jedis); 15 return result; 16 } 17 RedisPool.returnResource(jedis); 18 return result; 19 } 20 21 //exTime单位是s,设置session有效时间 22 //当用户初次登录的时候,需要设置有限期,存在redis session中 23 //后续如果用户再次请求登录,则只需要调用expire,重新设置有效期即可 24 public static String setEx(String key, String value, int exTime) { 25 Jedis jedis = null; 26 String result = null; 27 try { 28 jedis = RedisPool.getJedis(); 29 result = jedis.setex(key, exTime, value); 30 } catch (Exception e) { 31 log.error("setex key:{} value:{} error", key, value, e); 32 RedisPool.returnBrokenResource(jedis); 33 return result; 34 } 35 RedisPool.returnResource(jedis); 36 return result; 37 } 38 39 public static String set(String key, String value) { 40 Jedis jedis = null; 41 //jedis返回的结果 42 String result = null; 43 try { 44 jedis = RedisPool.getJedis(); 45 //设置key-value 46 result = jedis.set(key, value); 47 } catch (Exception e) { 48 log.error("set key:{} value:{} error", key, value, e); 49 RedisPool.returnBrokenResource(jedis); 50 return result; 51 } 52 RedisPool.returnResource(jedis); 53 return result; 54 } 55 56 public static String get(String key) { 57 Jedis jedis = null; 58 String result = null; 59 try { 60 jedis = RedisPool.getJedis(); 61 //根据key获取value值 62 result = jedis.get(key); 63 } catch (Exception e) { 64 log.error("set key:{} error", key, e); 65 RedisPool.returnBrokenResource(jedis); 66 return result; 67 } 68 RedisPool.returnResource(jedis); 69 return result; 70 } 71 72 public static Long del(String key) { 73 Jedis jedis = null; 74 Long result = null; 75 try { 76 jedis = RedisPool.getJedis(); 77 //根据key删除key-value 78 result = jedis.del(key); 79 } catch (Exception e) { 80 log.error("set key:{} error", key, e); 81 RedisPool.returnBrokenResource(jedis); 82 return result; 83 } 84 RedisPool.returnResource(jedis); 85 return result; 86 } 87 }