JedisPool

package com.java1234.redis;
 
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
 
/**
 * 测试类
 * @author user
 *
 */
public class JedisTest {
 
    public static void main(String[] args) {
        JedisPoolConfig config=new JedisPoolConfig(); // 连接池的配置对象
        config.setMaxTotal(100); // 设置最大连接数
        config.setMaxIdle(10); // 设置最大空闲连接数
         
        JedisPool jedisPool=new JedisPool(config,"192.168.1.107",6379);
         
        Jedis jedis=null;
        try{
            jedis=jedisPool.getResource(); // 获取连接
            jedis.auth("123456"); // 设置密码
            jedis.set("name""java知识分享网"); // 设置值
            String value=jedis.get("name"); // 获取值
            System.out.println(value);
             
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            if(jedis!=null){
                jedis.close();
            }
            if(jedisPool!=null){
                jedisPool.close();
            }
        }
    }
}


运行:

QQ鎴浘20170708233224.jpg

<think>我们正在讨论JedisPool,它是Jedis提供的连接池实现,用于管理Redis连接。连接池可以显著提高性能,因为创建和销毁连接是昂贵的操作。通过重用连接,可以减少这些开销。 根据引用内容,我们了解到: 1. 创建JedisPool需要配置JedisPoolConfig(设置最大连接数、最大空闲连接数等)和连接参数(主机、端口、超时等)。 2. 使用连接池时,通过getResource()方法获取连接,使用完成后调用close()方法将连接归还给连接池。 3. 使用管道(pipeline)可以进一步提升性能,特别是在批量操作时。 接下来,我将详细介绍JedisPool的使用方法、配置参数以及原理。 ## JedisPool详细介绍 ### 1. 什么是JedisPoolJedisPool是一个线程安全的Redis连接池。它基于Apache Commons Pool实现,用于管理多个Jedis实例(每个Jedis实例代表一个Redis连接)。连接池的主要目的是重用连接,减少频繁创建和销毁连接的开销,从而提高系统性能。 ### 2. 为什么需要连接池? - 创建和销毁连接是耗时操作(TCP三次握手、四次挥手)。 - 连接池可以限制同时使用的连接数量,防止系统过载。 - 重用连接可以减少资源消耗(如端口、内存)。 ### 3. 核心配置参数(通过JedisPoolConfig设置) | 参数 | 说明 | 默认值 | |------|------|--------| | maxTotal | 连接池最大连接数(包括空闲和使用中的连接) | 8 | | maxIdle | 连接池中最大空闲连接数 | 8 | | minIdle | 连接池中最小空闲连接数 | 0 | | testOnBorrow | 从连接池获取连接时是否测试连接可用性(建议设置为true以保证连接有效) | false | | testOnReturn | 归还连接时是否测试连接 | false | | testWhileIdle | 空闲时是否定期测试连接(建议开启) | false | | timeBetweenEvictionRunsMillis | 空闲连接扫描线程的运行间隔时间(毫秒) | -1(不运行) | | minEvictableIdleTimeMillis | 连接最小空闲时间(超过此时间可能被回收) | 30分钟 | | numTestsPerEvictionRun | 每次扫描最多检查的连接数 | 3 | ### 4. 创建JedisPool的步骤 #### 方式一:硬编码配置(如引用[1]所示) ```java // 1. 创建连接池配置 JedisPoolConfig config = new JedisPoolConfig(); config.setMaxTotal(30); // 最大连接数 config.setMaxIdle(10); // 最大空闲连接数 config.setMinIdle(5); // 最小空闲连接数(可选) config.setTestOnBorrow(true); // 获取连接时进行有效性测试(可选) // 2. 创建连接池 JedisPool jedisPool = new JedisPool( config, "localhost", // Redis主机地址 6379, // 端口 1800, // 连接超时时间(毫秒) null // 密码(如果没有密码则为null) ); // 3. 使用连接 try (Jedis jedis = jedisPool.getResource()) { // 执行Redis命令 jedis.set("key", "value"); String value = jedis.get("key"); System.out.println(value); } // try-with-resources会自动归还连接(调用jedis.close()) ``` #### 方式二:通过配置文件(如引用[2]所示) 首先创建配置文件`redis_pool.properties`(放在classpath下): ```properties redis_maxTotal=30 redis_maxIdle=15 redis_minIdle=5 redis_ip=127.0.0.1 redis_port=6379 redis_timeout=1800 # 如果有密码则配置 # redis_password=yourpassword ``` 然后读取配置文件创建连接池: ```java Properties props = new Properties(); try (InputStream input = getClass().getClassLoader().getResourceAsStream("redis_pool.properties")) { props.load(input); } JedisPoolConfig config = new JedisPoolConfig(); config.setMaxTotal(Integer.parseInt(props.getProperty("redis_maxTotal"))); config.setMaxIdle(Integer.parseInt(props.getProperty("redis_maxIdle"))); config.setMinIdle(Integer.parseInt(props.getProperty("redis_minIdle"))); String ip = props.getProperty("redis_ip"); int port = Integer.parseInt(props.getProperty("redis_port")); int timeout = Integer.parseInt(props.getProperty("redis_timeout")); String password = props.getProperty("redis_password"); // 可能为null JedisPool jedisPool = new JedisPool(config, ip, port, timeout, password); ``` ### 5. 使用JedisPool注意事项 - **连接归还**:使用完Jedis实例后,必须调用`close()`方法归还连接(否则会导致连接泄漏)。推荐使用`try-with-resources`语句(如上例)自动关闭。 - **异常处理**:如果连接在使用过程中发生异常,需要确保连接被销毁(而不是归还),避免污染连接池。Jedis已经做了处理,当发生异常时,调用`close()`会销毁连接,然后从池中申请新的连接。 - **线程安全**:JedisPool是线程安全的,但Jedis实例是非线程安全的。每个线程应该使用自己的Jedis实例。 ### 6. 高级用法:管道(Pipeline) 当需要执行大量命令时,使用管道可以显著减少网络往返时间(RTT)。引用[3]展示了管道带来的性能提升(20万次操作,使用管道耗时仅1188ms,而不使用管道耗时187242ms)。 ```java try (Jedis jedis = jedisPool.getResource()) { Pipeline pipeline = jedis.pipelined(); // 批量添加命令 for (int i = 0; i < 10000; i++) { pipeline.set("key" + i, "value" + i); } // 执行所有命令(不立即返回结果) pipeline.sync(); // 如果需要获取命令的返回结果,可以使用syncAndReturnAll // List<Object> results = pipeline.syncAndReturnAll(); } ``` ### 7. 连接池监控 可以通过以下方法监控连接池状态: ```java // 获取连接池的活动连接数(当前被使用的连接) int active = jedisPool.getNumActive(); // 获取连接池的空闲连接数 int idle = jedisPool.getNumIdle(); // 获取连接池的等待获取连接的线程数(如果设置了maxWaitMillis,当连接不足时,请求会等待) int waiters = jedisPool.getNumWaiters(); ``` ### 8. 连接池关闭 在应用关闭时,应该关闭连接池以释放资源: ```java jedisPool.close(); ``` ### 9. JedisPool原理 JedisPool内部使用Apache Commons Pool2来管理连接。当调用`getResource()`时: 1. 从池中获取一个空闲连接(如果有)。 2. 如果没有空闲连接且连接数未达到最大值,则创建一个新连接。 3. 如果连接数已达最大值,则等待(直到超时)其他连接释放。 连接归还(`close()`)时: - 如果连接正常,则将其标记为空闲,放回池中。 - 如果连接损坏(如连接中断)或已超过最大空闲时间,则销毁该连接。 §§相关问题§§ 1. JedisPool和JedisCluster有什么区别? 2. 如何配置JedisPool以实现最佳性能? 3. 使用JedisPool时如何处理连接泄漏? 4. JedisPool与Lettuce连接池相比有什么优缺点? </think>## JedisPool 详细介绍与使用指南 ### 一、JedisPool 核心原理 JedisPool 是 Redis Java 客户端 Jedis 提供的**连接池实现**,基于 Apache Commons Pool 2 构建。它通过管理和复用 Redis 连接,显著提升系统性能: - **连接复用**:避免频繁创建/销毁 TCP 连接的开销 - **资源控制**:限制最大连接数防止系统过载 - **健康检测**:自动验证连接有效性 - **线程安全**:内置并发控制机制 连接池工作流程: ```mermaid graph LR A[应用程序] --> B[JedisPool] B --> C{空闲连接?} C -->|是| D[分配空闲连接] C -->|否| E{达到maxTotal?} E -->|否| F[创建新连接] E -->|是| G[等待或抛异常] D & F --> H[业务操作] H --> I[归还连接] ``` ### 二、核心配置参数详解 通过 `JedisPoolConfig` 设置关键参数(示例配置如引用[2]所示): | 参数 | 说明 | 推荐值 | |------|------|--------| | `maxTotal` | 最大连接数 | 根据 QPS 设置<br>(公式:$maxTotal = \frac{QPS}{单连接吞吐}$) | | `maxIdle` | 最大空闲连接数 | 建议设为 $maxTotal \times 0.7$ | | `minIdle` | 最小空闲连接数 | 建议设为 $maxTotal \times 0.3$ | | `testOnBorrow` | 获取连接时校验 | true(生产环境必开) | | `testWhileIdle` | 空闲时定期校验 | true | | `timeBetweenEvictionRunsMillis` | 空闲连接扫描间隔 | 30000ms(30秒) | | `minEvictableIdleTimeMillis` | 连接最小空闲时间 | 600000ms(10分钟) | ### 三、完整使用示例 #### 1. 初始化连接池 ```java // 创建配置对象(引用[1]示例) JedisPoolConfig config = new JedisPoolConfig(); config.setMaxTotal(30); // 最大连接数 config.setMaxIdle(10); // 最大空闲连接 config.setMinIdle(5); // 最小空闲连接 config.setTestOnBorrow(true); // 获取连接时校验 // 创建连接池(引用[2]参数化配置) JedisPool jedisPool = new JedisPool( config, "localhost", // Redis地址 6379, // 端口 1800, // 连接超时(ms) null // 密码(无密码填null) ); ``` #### 2. 安全获取连接(推荐 try-with-resources) ```java try (Jedis jedis = jedisPool.getResource()) { // 执行命令 jedis.set("counter", "100"); String value = jedis.get("counter"); System.out.println("Counter value: " + value); } // 自动归还连接 ``` #### 3. 管道操作提升性能(引用[3]) ```java try (Jedis jedis = jedisPool.getResource()) { Pipeline pipeline = jedis.pipelined(); // 批量添加10,000个命令 for (int i = 0; i < 10000; i++) { pipeline.set("key" + i, "value" + i); } // 批量执行(网络往返1次) pipeline.sync(); } ``` ### 四、最佳实践建议 1. **连接泄漏防护** ```java // 强制回收泄漏连接(需定期执行) jedisPool.evict(); ``` 2. **监控关键指标** ```java System.out.println("活跃连接: " + jedisPool.getNumActive()); System.out.println("空闲连接: " + jedisPool.getNumIdle()); ``` 3. **异常处理** ```java try (Jedis jedis = jedisPool.getResource()) { // 业务代码 } catch (JedisConnectionException e) { // 处理连接异常 jedisPool.close(); // 严重异常时销毁连接池 } ``` 4. **优雅关闭** ```java Runtime.getRuntime().addShutdownHook(new Thread(() -> { jedisPool.close(); System.out.println("连接池已安全关闭"); })); ``` ### 五、性能优化策略 1. **连接数计算公式** 最优连接数 $N = \frac{系统QPS}{单连接吞吐量} \times 冗余系数(1.2-1.5)$ 2. **管道批处理** 如引用[3]测试所示: - 10万读写操作:无管道 **187秒** vs 管道 **1.2秒** - 适用场景:批量插入、统计计算等 3. **连接预热** ```java // 启动时初始化最小空闲连接 List<Jedis> minIdleList = new ArrayList<>(); for (int i = 0; i < config.getMinIdle(); i++) { minIdleList.add(jedisPool.getResource()); } minIdleList.forEach(Jedis::close); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值