zoukankan      html  css  js  c++  java
  • 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  
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    机器学习笔记
    使用pelican创建静态博客
    farbox editor是个好东西
    MamBa项目的插件编写-TikiTorch生成器
    通过rundll32运行C#DLL转储内存
    通过调用Windows本地RPC服务器bypass UAC
    浅谈python反序列化漏洞
    [转载]SQL Server提权系列
    certutil在传输payload中的新奇技巧
    AVIator -- Bypass AV tool
  • 原文地址:https://www.cnblogs.com/silyvin/p/10130687.html
Copyright © 2011-2022 走看看