redis 连接池 实践

关键参数:

            config.setMaxTotal(5);
            config.setMaxIdle(2);
            config.setMinIdle(1);
            config.setMaxWaitMillis(1500);

最大连接数

空闲连接超过maxidle,直接销毁

空闲连接不超过maxidle,等待一定时间后销毁至minidle

连接达到5,再申请一个连接,等待1.5秒未果后,抛出异常

实践代码:

            config.setMaxTotal(50);
            config.setMaxIdle(20);
            config.setMinIdle(10);
            config.setMaxWaitMillis(1500);
        for(int i=0; i< 51; ++i) {
            try {
                Jedis jedis = RedisPoolUtil.getConn();
                jedis.set("test", "test");
                // 故意不归还
                //    RedisPoolUtil.closeConn(jedis);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

(原来有14个连接其它项目)

同时超出的1个报异常:

[INFO] 2018-12-22 16:48:26 446 [com.jds.WxEnterprise.common.RedisPoolUtil] [main] (RedisPoolUtil.java:43) -> redis线程池被成功初始化
redis.clients.jedis.exceptions.JedisException: Could not get a resource from the pool
    at redis.clients.util.Pool.getResource(Pool.java:51)
    at redis.clients.jedis.JedisPool.getResource(JedisPool.java:226)
    at com.jds.WxEnterprise.common.RedisPoolUtil.getConn(RedisPoolUtil.java:62)
    at com.jds.WxEnterprise.service.RedisService.calInRedis(RedisService.java:28)
    at com.jds.WxEnterprise.WxEnterpriseDataServer.main(WxEnterpriseDataServer.java:60)
Caused by: java.util.NoSuchElementException: Timeout waiting for idle object
    at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:448)
    at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:362)
    at redis.clients.util.Pool.getResource(Pool.java:49)
    ... 4 more

实例

https://blog.csdn.net/wx5040257/article/details/78474157

环境:jdk1.7    redis3.2.8

所需jar包:jedis-2.9.0.jar     commons-pool2-2.3

Jedis连接池使用步骤如下:
1->获取Jedis实例需要从JedisPool中获取;
2->用完Jedis实例需要返还给JedisPool;
3->如果Jedis在使用过程中出错,则也需要还给JedisPool;

=================连接池参数配置文件redis.properties================

    #*****************jedis连接参数设置*********************
    #redis服务器ip
    redis.ip=169.254.130.122
    #redis服务器端口号
    redis.port=6379
    #redis访问密码
    redis.passWord=test123
    #与服务器建立连接的超时时间
    redis.timeout=3000
    #************************jedis池参数设置*******************
    #jedis的最大活跃连接数
    jedis.pool.maxActive=100
    #jedis最大空闲连接数
    jedis.pool.maxIdle=50
    #jedis池没有连接对象返回时,等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。
    #如果超过等待时间,则直接抛出JedisConnectionException
    jedis.pool.maxWait=1500
    #从池中获取连接的时候,是否进行有效检查
    jedis.pool.testOnBorrow=true
    #归还连接的时候,是否进行有效检查
    jedis.pool.testOnReturn=true

=================Redis连接池工具类RedisPoolUtil================

    package com.wx.utils;
     
    import java.util.Properties;
    import redis.clients.jedis.Jedis;
    import redis.clients.jedis.JedisPool;
    import redis.clients.jedis.JedisPoolConfig;
     
    /**
     * Redis连接池工具类
     */
    public class RedisPoolUtil {
        private static JedisPool jedisPool = null;
        private static String redisConfigFile = "redis.properties";
        //把redis连接对象放到本地线程中
        private static ThreadLocal<Jedis> local=new ThreadLocal<Jedis>();
        
        //不允许通过new创建该类的实例
        private RedisPoolUtil() {
        }
     
        /**
         * 初始化Redis连接池
         */
        public static void initialPool() {
            try {
                Properties props = new Properties();
                //加载连接池配置文件
                props.load(RedisPoolUtil.class.getClassLoader().getResourceAsStream(redisConfigFile));
                // 创建jedis池配置实例
                JedisPoolConfig config = new JedisPoolConfig();
                // 设置池配置项值
                config.setMaxTotal(Integer.valueOf(props.getProperty("jedis.pool.maxActive")));
                config.setMaxIdle(Integer.valueOf(props.getProperty("jedis.pool.maxIdle")));
                config.setMaxWaitMillis(Long.valueOf(props.getProperty("jedis.pool.maxWait")));
                config.setTestOnBorrow(Boolean.valueOf(props.getProperty("jedis.pool.testOnBorrow")));
                config.setTestOnReturn(Boolean.valueOf(props.getProperty("jedis.pool.testOnReturn")));
                // 根据配置实例化jedis池
                jedisPool = new JedisPool(config, props.getProperty("redis.ip"),
                        Integer.valueOf(props.getProperty("redis.port")),
                        Integer.valueOf(props.getProperty("redis.timeout")),
                        props.getProperty("redis.passWord"));
                System.out.println("线程池被成功初始化");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        
        /**
         * 获得连接
         * @return Jedis
         */
        public static Jedis getConn() {
            //Redis对象
            Jedis jedis =local.get();
            if(jedis==null){
                if (jedisPool == null) {    
                    initialPool();  
                }
                jedis = jedisPool.getResource();
                local.set(jedis);
            }
            return jedis;  
        }
        
        //新版本用close归还连接
        public static void closeConn(){
            //从本地线程中获取
            Jedis jedis =local.get();
            if(jedis!=null){
                jedis.close();
            }
            local.set(null);
        }
        
        //关闭池
        public static void closePool(){
            if(jedisPool!=null){
                jedisPool.close();
            }
        }
    }


============线程测试类============

    package com.wx.test;
     
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import com.wx.utils.RedisPoolUtil;
    import redis.clients.jedis.Jedis;
     
    public class TestPool {
        public static void main(String[] args) {
            //初始化连接池
            RedisPoolUtil.initialPool();
            //启动1000个线程
            for (int i = 0; i < 1000; i++) {            
                ClientThread t = new ClientThread(i);  
                t.start();  
            }
        }  
    }
    //线程类
    class ClientThread extends Thread {  
        int i = 0;  
        public ClientThread(int i) {  
            this.i = i;  
        }  
        public void run() {  
            Jedis jedis=RedisPoolUtil.getConn();
            Date date = new Date();  
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");  
            String time = sdf.format(date);  
            jedis.set("key"+i, time);
            try {
                //每次睡眠一个随机时间
                Thread.sleep((int)(Math.random()*5000));
                String foo = jedis.get("key"+i);        
                System.out.println("【输出>>>>】key:" + foo + " 第:"+i+"个线程");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                RedisPoolUtil.closeConn();
            }
        }  
    }  

运行过程中,去服务器看连接数

    127.0.0.1:6379> info clients
    # Clients
    connected_clients:102
    client_longest_output_list:0
    client_biggest_input_buf:0
    blocked_clients:0
    127.0.0.1:6379> info clients
    # Clients
    connected_clients:70
    client_longest_output_list:0
    client_biggest_input_buf:0
    blocked_clients:0
    127.0.0.1:6379> info clients
    # Clients
    connected_clients:53
    client_longest_output_list:0
    client_biggest_input_buf:0
    blocked_clients:0
    127.0.0.1:6379> info clients
    # Clients
    connected_clients:2
    client_longest_output_list:0
    client_biggest_input_buf:0
    blocked_clients:0
    127.0.0.1:6379> info clients
    # Clients
    connected_clients:2
    client_longest_output_list:0
    client_biggest_input_buf:0
    blocked_clients:0
    127.0.0.1:6379>

可以看出连接池中最大100个活跃连接迅速被占满,(最开始102个是因为我单独启动了两个连接)

然后连接用完了,迅速归还连接

java端的运行结果


可以看出有超时没拿到连接的报错!

ok,测试成功!
---------------------  
作者:御前两把刀刀  
来源:CSDN  
原文:https://blog.csdn.net/wx5040257/article/details/78474157  
版权声明:本文为博主原创文章,转载请附上博文链接!

原文地址:https://www.cnblogs.com/silyvin/p/10130687.html