Java连接Docker部署的Redis时报无法从连接池获取资源错误
故障原因
- 错误根源是初始化
JedisPool时传入的主机地址带了http://协议前缀。Jedis是基于TCP的Redis客户端,连接时不需要HTTP协议头,JedisPool的主机参数只接受纯主机名或IP,不会自动解析URL格式的地址,传入带协议头的字符串会直接导致主机解析失败,无法创建底层连接,最终抛出无法从连接池获取资源的异常。 - 你测试用的废弃单连接构造方法内部做了URL兼容逻辑,会自动剥离
http://前缀所以能正常连通,但这套兼容逻辑没有在JedisPool的构造流程中实现,才会出现单连接能通、连接池连不上的特殊现象。 - 你贴的Docker Compose配置没有问题,端口映射、密码配置、持久化配置都是正常的,不需要调整容器侧的任何设置。
合规实现方案
首先确保使用3.x及以上版本的Jedis依赖,不要使用过旧版本,以下是无废弃API的标准写法:
import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; import java.time.Duration; public class RedisConnectionDemo { // 连接池是重量级资源,全局初始化单例即可,不要重复创建 private static final JedisPool JEDIS_POOL; static { JedisPoolConfig poolConfig = new JedisPoolConfig(); // 按需调整连接池参数 poolConfig.setMaxTotal(8); poolConfig.setMaxIdle(4); poolConfig.setMinIdle(2); poolConfig.setMaxWait(Duration.ofSeconds(2)); poolConfig.setTestWhileIdle(true); // 注意:主机参数直接传localhost,不要带任何协议前缀 JEDIS_POOL = new JedisPool( poolConfig, "localhost", 6379, (int) Duration.ofSeconds(3).toMillis(), "thisismypassword" ); } public static void main(String[] args) { // 用try-with-resources自动归还连接,避免连接泄漏 try (Jedis jedis = JEDIS_POOL.getResource()) { System.out.println("PING结果:" + jedis.ping()); jedis.set("demo_key", "demo_value"); System.out.println("查询结果:" + jedis.get("demo_key")); } catch (Exception e) { e.printStackTrace(); } finally { // 程序退出时关闭连接池 JEDIS_POOL.close(); } } }
其他可选合规写法
如果你习惯用URL格式配置连接地址,可以使用JedisPool提供的URI参数构造方法,这也是官方支持的非废弃API:
// 连接串格式:redis://:密码@主机:端口 JEDIS_POOL = new JedisPool(poolConfig, URI.create("redis://:thisismypassword@localhost:6379"));
注意事项
- 不要每次执行Redis操作都新建JedisPool实例,连接池只需要在程序启动时初始化一次,重复创建会产生大量无效TCP连接,浪费资源。
- 从连接池获取的Jedis实例用完必须归还,优先使用try-with-resources语法自动处理,不需要手动调用close方法。
- 不要在主机参数中携带任何协议前缀,除非使用专门的URI构造方法。
内容的提问来源于stack exchange,提问作者Samik Biswas
相关产品推荐
相关产品推荐

