redis连接释放问题记录

redis连接释放问题记录

记录一次在压测后发现的redisTemplate使用场景下,redis的连接资源没有释放的问题。

问题描述

springboot 版本:2.1.2(排除了lettuce的依赖)

jedis版本:2.9.1

场景:高并发情况下,RedisTemplate获取连接失败并阻塞线程导致TPS下降。

异常描述:如果设置了max-wait则在等待时间到后抛出异常:Timeout waiting for idle object。如果没有设置,则线程将被一直阻塞。

问题追踪

public T borrowObject(long borrowMaxWaitMillis) throws Exception {
    //.....
                                p = (PooledObject)this.idleObjects.takeFirst();
                            } else {
                                p = (PooledObject)this.idleObjects.pollFirst(borrowMaxWaitMillis, TimeUnit.MILLISECONDS);
                            }
                        }

                        if (p == null) {
                            throw new NoSuchElementException("Timeout waiting for idle object");
                        }
                    //.......
}

阻塞点在this.idleObjects.takeFirst()方法,如果设置了等待时间,则调用pollFirst()。debug可以发现,资源没有释放。

这个可以看当前对象中的borrowedCount和returnedCount发现,borrowedCount大于returnedCount。

borrowedCount:借用的资源计数

returnedCount:归还的资源计数

问题定位

borrowObject(long borrowMaxWaitMillis):获取资源的方法

returnObject(T obj):归还资源的方法

本来以为是归还资源的方法有bug导致的资源没有归还,但是经过多次debug分析后,发现问题点实际在于jedis的close方法上。

public void close() {
    if (this.dataSource != null) {
        if (this.client.isBroken()) {
            this.dataSource.returnBrokenResource(this);
        } else {
            this.dataSource.returnResource(this);
        }
		//问题点在于这里
        this.dataSource = null;
    } else {
        super.close();
    }
}

场景描述:

在多线程环境下,通过debug可以看到,当前jedis对象是共享的。

假如有线程1,2.

当线程1获取的资源的持有,线程2等待资源释放场景。

然后线程1在执行close时,通过returnResource释放了资源,而线程2拿到了资源。

然后线程2也执行到了close方法,而线程1执行了this.dataSource = null;

这时线程2则不会归还资源,直接执行了close,导致出现的连接没有释放问题。

问题解决

GitHub Issues描述

解决方式:

  1. 升级jedis版本或者回退jedis版本。
  2. 更换连接,可以考虑使用lettuce。
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值