Redis连接池耗尽,如何快速定位异常原因?
摘要:转载请注明出处: 最近在项目中遇到一个奇怪的现象,项目运行环境中的redis在业务运行中,一直没有更新redis的值,在服务的日志中也没有看到相关的异常,导致服务看起来正常,但和redis相关的功能却没有更新。记录下这个异常定位解决的过程。
转载请注明出处:
最近在项目中遇到一个奇怪的现象,项目运行环境中的redis在业务运行中,一直没有更新redis的值,在服务的日志中也没有看到相关的异常,导致服务看起来正常,但和redis相关的功能却没有更新。记录下这个异常定位解决的过程。
登录到redis里面,发现redis也是运行正常的,且能正常获取。所以进入到了服务端里面,获取jvm线程进行具体分析,看到有很多个线程栈如下:
定位分析过程
pool-4-thread-1:
线程名称,表明该线程属于线程池pool-4的第一个工作线程(线程池通常由ThreadPoolExecutor管理)。
Id=211:
JVM 内部分配的线程唯一标识符(非操作系统线程ID)。
CPU 时间统计
cpu=692644037380 ns usr=644020000000 ns
cpu=692644037380 ns:
线程从启动至今消耗的总 CPU 时间(包括内核态和用户态),单位为纳秒(≈ 692.64 秒)。
usr=644020000000 ns:
线程在用户态(User Mode)消耗的 CPU 时间(≈ 644.02 秒)。
差值意义:cpu - usr ≈ 48.62秒为线程在内核态(Kernel Mode)的耗时,通常由系统调用(如 I/O、锁竞争)引起。
线程阻塞与等待统计
blocked 2294 for -1 ms waited 28442 for -1 ms
blocked 2294:
线程因竞争锁(synchronized)而被阻塞的次数(总计 2294 次)。
for -1 ms:
阻塞时间的统计方式,-1 ms表示未记录具体阻塞时长(需启用 JVM 参数-XX:+PrintBlocked获取)。
waited 28442:
线程在等待条件触发(如Object.wait()或Condition.await())的次数(总计 28442 次)。
for -1 ms:
等待时间的统计方式,-1 ms表示未记录具体等待时长(需启用-XX:+PrintWait获取)。
线程状态与堆栈跟踪
java.lang.Thread.State: WAITING
at sun.misc.Unsafe.park(Native Method)
- waiting on (a java.util.concurrent.ThreadPoolExecutor$Worker@5cf37a65)
Thread.State: WAITING:
线程处于无限期等待状态,通常由以下操作触发:
Object.wait()(无超时参数)。
LockSupport.park()。
Condition.await()(无超时参数)。
sun.misc.Unsafe.park(Native Method):
线程通过LockSupport.park()进入阻塞状态,底层调用Unsafe.park()。
waiting on (a java.util.concurrent.ThreadPoolExecutor$Worker@5cf37a65):
线程正在等待ThreadPoolExecutor.Worker对象(线程池工作线程的封装)关联的条件变量(如任务队列非空)。
