news 2026/8/12 20:04:23

Jedis连接池

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Jedis连接池

一、前言:为什么必须用连接池?

在 Java 应用中直接使用new Jedis()创建单连接操作 Redis,看似简单,但在高并发场景下会迅速崩溃

  • ❌ 每次请求新建 TCP 连接 → 耗时(毫秒级)
  • ❌ 频繁创建/销毁连接 → 系统资源耗尽(文件描述符、内存)
  • ❌ 无法控制并发连接数 → Redis 服务被压垮

Jedis 连接池(JedisPool)通过复用连接、限制资源、自动回收,成为生产环境的唯一选择

本文将带你:
✅ 深入理解 JedisPool 工作原理
✅ 掌握核心参数配置
✅ 避免常见陷阱(如连接泄漏)
✅ 实现生产级封装与监控


二、JedisPool 核心原理

JedisPool 基于Apache Commons Pool2实现,其核心思想是:

预先创建一批 Jedis 连接,放入“池”中;业务需要时从池中借(borrow),用完归还(return)

关键特性

  • 线程安全:多个线程可并发 borrow/return
  • 自动检测:可配置测试连接有效性
  • 资源隔离:限制最大连接数,防止单点打爆 Redis

三、JedisPool 基础配置与使用

3.1 Maven 依赖

<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>5.1.2</version> </dependency> <!-- JedisPool 依赖 commons-pool2,但 Jedis 已传递引入 -->

3.2 创建连接池(带密码 & 超时)

import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; public class JedisPoolManager { private static volatile JedisPool jedisPool = null; public static JedisPool getJedisPool() { if (jedisPool == null) { synchronized (JedisPoolManager.class) { if (jedisPool == null) { jedisPool = createJedisPool(); } } } return jedisPool; } private static JedisPool createJedisPool() { JedisPoolConfig config = new JedisPoolConfig(); // ===== 核心参数配置 ===== config.setMaxTotal(50); // 最大连接数 config.setMaxIdle(20); // 最大空闲连接 config.setMinIdle(5); // 最小空闲连接(保持 warm) config.setMaxWaitMillis(2000); // 获取连接最大等待时间(ms) config.setTestOnBorrow(true); // 借出时检查有效性 config.setTestOnReturn(false); // 归还时不检查(影响性能) config.setTestWhileIdle(true); // 空闲时检查(配合 timeBetweenEvictionRunsMillis) config.setTimeBetweenEvictionRunsMillis(30000); // 空闲检查周期 config.setMinEvictableIdleTimeMillis(60000); // 连接最小空闲时间才可被驱逐 // 创建连接池(含密码、超时) return new JedisPool( config, "192.168.1.100", // Redis 地址 6379, // 端口 2000, // 连接超时(ms) "your_password", // 密码(无密码传 null) 0 // database(默认 0) ); } // 优雅关闭 public static void destroyPool() { if (jedisPool != null) { jedisPool.close(); } } }

四、正确使用连接池:避免连接泄漏!

4.1 错误写法(会导致连接泄漏!)

// ❌ 危险!未关闭连接 public String get(String key) { Jedis jedis = JedisPoolManager.getJedisPool().getResource(); return jedis.get(key); // jedis 没有 close()!连接永远不归还 → 池耗尽 }

4.2 正确写法:try-with-resources(推荐)

// ✅ 推荐:自动 close() public String get(String key) { try (Jedis jedis = JedisPoolManager.getJedisPool().getResource()) { return jedis.get(key); } // 自动调用 jedis.close() → 归还连接 }

4.3 手动 close(兼容老版本 Java)

// ✅ 兼容 Java 7- public String get(String key) { Jedis jedis = null; try { jedis = JedisPoolManager.getJedisPool().getResource(); return jedis.get(key); } finally { if (jedis != null) { jedis.close(); // 注意:不是销毁,而是归还! } } }

🔑关键点
jedis.close()在连接池模式下 =归还连接,不是关闭 TCP!


五、生产级封装:通用 Redis 工具类

public class RedisUtils { private static final JedisPool jedisPool = JedisPoolManager.getJedisPool(); // String public static void set(String key, String value) { try (Jedis jedis = jedisPool.getResource()) { jedis.set(key, value); } } public static String get(String key) { try (Jedis jedis = jedisPool.getResource()) { return jedis.get(key); } } // Hash public static void hset(String key, String field, String value) { try (Jedis jedis = jedisPool.getResource()) { jedis.hset(key, field, value); } } public static String hget(String key, String field) { try (Jedis jedis = jedisPool.getResource()) { return jedis.hget(key, field); } } // 带过期时间 public static void setEx(String key, int seconds, String value) { try (Jedis jedis = jedisPool.getResource()) { jedis.setex(key, seconds, value); } } // 批量操作(Pipeline) public static void batchSet(Map<String, String> kvs) { try (Jedis jedis = jedisPool.getResource()) { Pipeline p = jedis.pipelined(); kvs.forEach(p::set); p.sync(); // 执行 } } }

六、连接池参数调优指南

参数默认值生产建议说明
maxTotal850~200总连接数 = QPS × 平均响应时间(秒)
maxIdle8maxTotal避免频繁创建连接
minIdle05~10保持 warm 连接,应对突发流量
maxWaitMillis-1(无限)1000~3000 ms防止线程无限阻塞
testOnBorrowfalsetrue(开发)
false(生产)
借出时检查(增加 RT)
testWhileIdlefalsetrue后台定期清理无效连接

💡计算 maxTotal 示例

  • 预期 QPS = 1000
  • Redis 平均响应时间 = 2ms
    → 所需连接数 ≈ 1000 × 0.002 =2
    但考虑峰值、网络抖动,建议设为20~50

七、监控与故障排查

7.1 监控连接池状态

JedisPool pool = JedisPoolManager.getJedisPool(); GenericObjectPool<Jedis> internalPool = pool.getPool(); System.out.println("活跃连接: " + internalPool.getNumActive()); System.out.println("空闲连接: " + internalPool.getNumIdle()); System.out.println("等待线程: " + internalPool.getNumWaiters());

7.2 常见问题排查

现象可能原因解决方案
java.util.NoSuchElementException: Timeout waiting for idle object连接池耗尽增大maxTotal,检查是否连接泄漏
应用启动后 Redis 连接数暴增minIdle设置过高调整minIdle或延迟初始化
偶尔读到旧数据连接未清理(脏连接)开启testWhileIdle+ 合理设置timeBetweenEvictionRunsMillis

八、高级技巧:多 Redis 实例支持

// 支持多个 Redis 实例(如 cache / session 分离) public class MultiJedisPoolManager { private static Map<String, JedisPool> poolMap = new ConcurrentHashMap<>(); public static JedisPool getPool(String name) { return poolMap.computeIfAbsent(name, k -> createPoolByConfig(k)); } private static JedisPool createPoolByConfig(String name) { // 根据 name 读取不同配置(如从 application.yml) // 返回对应 JedisPool } } // 使用 JedisPool cachePool = MultiJedisPoolManager.getPool("cache"); JedisPool sessionPool = MultiJedisPoolManager.getPool("session");

九、结语

感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/14 15:46:10

SpringDataRedis快速入门

一、前言&#xff1a;为什么用 Spring Data Redis&#xff1f;在 Spring Boot 项目中&#xff0c;直接使用 Jedis 或 Lettuce 操作 Redis 虽然灵活&#xff0c;但存在以下问题&#xff1a;❌ 需手动管理连接、异常处理❌ 序列化/反序列化逻辑重复❌ 无法享受 Spring 的依赖注入…

作者头像 李华
网站建设 2026/7/14 15:46:09

PAT 乙级 1044

这题还真是坑人。比如 26 转化成火星文&#xff0c;有了高位&#xff0c;就不要低位了&#xff0c;这种情况要单独讨论。#include<bits/stdc.h> using namespace std;int main() {string a[13] {"tret", "jan", "feb", "mar", …

作者头像 李华
网站建设 2026/7/14 15:46:07

第三方应用程序漏洞和木马制作小实验

中华人民共和国网络安全法 任何个人和组织不得从事非法侵入他人网络、干扰他人网络正常功能、窃取网络数据等危害网络安全的活动;不得提供专门用于从事侵入网络、干扰网络正常功能及防护措施、窃取网络数据等危害网络安全活动的程序、工具:明知他人从事危害网络安全的活动的&am…

作者头像 李华
网站建设 2026/7/14 15:46:13

Asian Beauty Z-Image Turbo 生成原理浅析:从卷积神经网络到扩散模型

Asian Beauty Z-Image Turbo 生成原理浅析&#xff1a;从卷积神经网络到扩散模型 每次看到AI生成的精致人像&#xff0c;尤其是那些充满东方美学韵味的作品&#xff0c;你是不是也会好奇&#xff1a;这到底是怎么做到的&#xff1f;一张原本充满噪点的图片&#xff0c;怎么就一…

作者头像 李华