spring-data-redis 连接泄漏,我 TM 人傻了 (4)

在这个例子中,会发生连接泄漏,首先执行:

redisTemplate.execute(new SessionCallback<Object>() { @Override public <K, V> Object execute(RedisOperations<K, V> operations) throws DataAccessException { Cursor<Map.Entry<Object, Object>> scan = operations.opsForHash().scan((K) "key".getBytes(), ScanOptions.scanOptions().match("*").count(1000).build()); //scan 最后一定要关闭,这里采用 try-with-resource try (scan) { } catch (IOException e) { e.printStackTrace(); } return null; } });

这样呢,LettuceConnection 会和当前线程绑定,并且在结束时,引用计数不为零,而是 1。并且 cursor 关闭时,会调用 LettuceConnection 的 close。但是 LettuceConnection 的 close 的实现,其实只是标记状态,并且把独占的连接 asyncDedicatedConn 关闭,由于当前没有使用到独占的连接,所以为空,不需要关闭;如下面源码所示:

LettuceConnection:

@Override public void close() throws DataAccessException { super.close(); if (isClosed) { return; } isClosed = true; if (asyncDedicatedConn != null) { try { if (customizedDatabaseIndex()) { potentiallySelectDatabase(defaultDbIndex); } connectionProvider.release(asyncDedicatedConn); } catch (RuntimeException ex) { throw convertLettuceAccessException(ex); } } if (subscription != null) { if (subscription.isAlive()) { subscription.doClose(); } subscription = null; } this.dbIndex = defaultDbIndex; }

之后我们继续执行一个 Pipeline 命令:

List<Object> objects = redisTemplate.executePipelined(new RedisCallback<Object>() { @Override public Object doInRedis(RedisConnection connection) throws DataAccessException { connection.get("test".getBytes()); redisTemplate.opsForValue().get("test"); return null; } });

这时候由于连接已经绑定到当前线程,同时同上上一节分析我们知道第一步解开释放这个绑定,但是调用了 LettuceConnection 的 close。执行这个代码,会创建一个独占连接,并且,由于计数不能归零,导致连接一直与当前线程绑定,这样,这个独占连接一直不会关闭(如果有连接池的话,就是一直不返回连接池)

即使后面我们手动关闭这个链接,但是根据源码,由于状态 isClosed 已经是 true,还是不能将独占链接关闭。这样,就会造成连接泄漏

针对这个 Bug,我已经向 spring-data-redis 一个 Issue:Lettuce Connection Leak while using execute(SessionCallback) and executeWithStickyConnection in same thread by random turn

image

尽量避免使用 SessionCallback,尽量仅在需要使用 Redis 事务的时候,使用 SessionCallback。

使用 SessionCallback 的函数单独封装,将事务相关的命令单独放在一起,并且外层尽量避免再继续套 RedisTemplate 的 execute 相关函数。

微信搜索“我的编程喵”关注公众号,每日一刷,轻松提升技术,斩获各种offer

spring-data-redis 连接泄漏,我 TM 人傻了

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwpzyx.html