记一次MyBatis使用Redis二级缓存造成(Could not get a resource from the pool)的坑

本文介绍了解决MyBatis使用远程Redis作为二级缓存时出现连接池问题的方法。通过调整配置文件的命名规范,成功解决了连接超时的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

问题复现:

解决方法

源码分析


问题复现:

最近在项目中测试使用redis作为mybatis的二级缓存。

由于我的redis是部署在阿里云服务器上的,造成了redis一直无法获取到连接。

报异常信息如下:

org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool

org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
### Cause: redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool

	at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:150)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:141)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:77)
	at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:82)
	at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:59)
	at com.sun.proxy.$Proxy28.findUserById(Unknown Source)
	at com.lagou.test.CacheTest.SecondLevelCache(CacheTest.java:61)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
Caused by: redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
	at redis.clients.util.Pool.getResource(Pool.java:50)
	at redis.clients.jedis.JedisPool.getResource(JedisPool.java:99)
	at org.mybatis.caches.redis.RedisCache.execute(RedisCache.java:51)
	at org.mybatis.caches.redis.RedisCache.getObject(RedisCache.java:88)
	at org.apache.ibatis.cache.decorators.LoggingCache.getObject(LoggingCache.java:57)
	at org.apache.ibatis.cache.decorators.TransactionalCache.getObject(TransactionalCache.java:68)
	at org.apache.ibatis.cache.TransactionalCacheManager.getObject(TransactionalCacheManager.java:35)
	at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:101)
	at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:83)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.apache.ibatis.plugin.Invocation.proceed(Invocation.java:49)
	at com.github.pagehelper.SqlUtil._processPage(SqlUtil.java:247)
	at com.github.pagehelper.SqlUtil.processPage(SqlUtil.java:229)
	at com.github.pagehelper.PageHelper.intercept(PageHelper.java:118)
	at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:61)
	at com.sun.proxy.$Proxy27.query(Unknown Source)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.apache.ibatis.plugin.Invocation.proceed(Invocation.java:49)
	at tk.mybatis.mapper.mapperhelper.MapperInterceptor.intercept(MapperInterceptor.java:61)
	at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:61)
	at com.sun.proxy.$Proxy27.query(Unknown Source)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:148)
	... 29 more
Caused by: redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: connect timed out
	at redis.clients.jedis.Connection.connect(Connection.java:164)
	at redis.clients.jedis.BinaryClient.connect(BinaryClient.java:80)
	at redis.clients.jedis.BinaryJedis.connect(BinaryJedis.java:1676)
	at redis.clients.jedis.JedisFactory.makeObject(JedisFactory.java:87)
	at org.apache.commons.pool2.impl.GenericObjectPool.create(GenericObjectPool.java:861)
	at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:435)
	at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:363)
	at redis.clients.util.Pool.getResource(Pool.java:48)
	... 56 more
Caused by: java.net.SocketTimeoutException: connect timed out
	at java.base/java.net.PlainSocketImpl.waitForConnect(Native Method)
	at java.base/java.net.PlainSocketImpl.socketConnect(PlainSocketImpl.java:107)
	at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:399)
	at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:242)
	at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:224)
	at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
	at java.base/java.net.Socket.connect(Socket.java:608)
	at redis.clients.jedis.Connection.connect(Connection.java:158)
	... 63 more

 先上配置文件:redis.properties

redis.host=x.x.x.x
redis.port=6379
redis.connectionTimeout=5000
redis.password=xxx
redis.database=0 

解决方法

先说解决方法:

把redis.properties的配置文件中redis.去掉,运行结果就可以了。

host=x.x.x.x
port=6379
connectionTimeout=60000
password=xxx
database=0

运行如下:

源码分析

数据库mybatis的配置文件:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/zdy_mybatis?characterEncoding=utf8
jdbc.username=root
jdbc.password=xxxx

我在mybatis的配置文件中开启了二级缓存:

<setting name="cacheEnabled" value="true"/>

并且在mapper.xml文件中指定redis作为二级缓存:

<cache type="org.mybatis.caches.redis.RedisCache" />

并编写好测试代码准备运行:

    @Test
    public void secondLevelCache(){
        SqlSession sqlSession1 = sqlSessionFactory.openSession();
        SqlSession sqlSession2 = sqlSessionFactory.openSession();

        UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
        UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);

        User user1 = mapper1.findById(1);
        sqlSession1.close();
        User user2 = mapper2.findById(1);

        System.out.println(user1 == user2);
    }

发现一直无法获取到redis的链接。报错信息为:org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool

经过源码跟踪发现:

创建JedisFactory时并没有获取到我配置的参数,接着往读取配置文件路径的地方跟踪,最终来到RedisConfigurationBuilder的parseConfiguration方法

发现他是正常获取到了我的配置文件路径,那么错误可能不是在这里发生的,证明如下,接着往下跟踪:

 如上图,正常获取到了config对象封装起来。那么问题应该就在setConfigProperties这个方法了,

经过debugger发现始终无法进入到 if 判断里面,推测可能是name属性不一致:

于是尝试把了redis.properties配置文件中,redis.的地方删除掉,再次跟踪到这里,发现终于可以进入到if判断了。于是问题得以解决。

 最后测试类运行如下:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值