日常Bug排查-系统失去响应-Redis使用不当

前言

日常Bug排查系列都是一些简单Bug排查,笔者将在这里介绍一些排查Bug的简单技巧,同时顺便积累素材_

Bug现场

开发反应线上系统出现失去响应的现象,收到业务告警已经频繁MarkAndSweep(Full GC)告警。于是找到笔者进行排查。

看基础监控

首先呢,当然是看我们的监控了,找到对应失去响应的系统的ip,看下我们的基础监控。



机器内存持续上升。因为我们是java系统,堆的大小一开始已经设置了最大值。

--XX:Xms2g -Xmx2g

所以看上去像堆外内存泄露。而FullGC告警只是堆外内存后一些关联堆内对象触发。

看应用监控

第二步,当然就是观察我们的应用监控,这边笔者用的是CAT。观察Cat中对应应用的情况,很容易发现,其ActiveThread呈现不正常的现象,竟然达到了5000+多个,同时和内存上升曲线保持一致。

jstack

java应用中遇到线程数过多的现象,首先我们考虑的是jstack,jstack出来对应的文件后。我们less一下,发现很多线程卡在下面的代码栈上。

"Thread-1234
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park
......
at org.apache.commons.pool2.impl.LinkedBlockingQueue.takeFirst
......
at redis.clients.util.Pool.getResource

很明显的,这个代码栈值得是没有获取连接,从而卡住。至于为什么卡这么长时间而不释放,肯定是由于没设置超时时间。那么是否大部分线程都卡在这里呢,这里我们做一下统计。

cat jstack.txt | grep 'prio=' | wc -l
======> 5648
cat jstack.txt | grep 'redis.clients.util.Pool.getResource'
======> 5242

可以看到,一共5648个线程,有5242,也就是92%的线程卡在Redis getResource中。

看下redis情况

netstat -anp | grep 6379
tcp 0 0 1.2.3.4:111 3.4.5.6:6379 ESTABLISHED
......

一共5个,而且连接状态为ESTABLISHED,正常。由此可见他们配置的最大连接数是5(因为别的线程正在得到获取Redis资源)。

Redis连接泄露

那么很自然的想到,Redis连接泄露了,即应用获得Redis连接后没有还回去。这种泄露有下面几种可能:

情况1:



情况2:



情况3:

调用Redis卡住,由于其它机器是好的,故排除这种情况。

如何区分

我们做个简单的推理:

如果是情况1,那么这个RedisConn肯定可以通过内存可达性分析和Thread关联上,而且这个关联关系肯定会关联到某个业务操作实体(例如code stack or 业务bean)。那么我们只要观察其在堆内的关联路线是否和业务相关即可,如果没有任何关联,那么基本断定是情况2了。

可达性分析

我们可以通过jmap dump出应用内存,然后通过MAT(Memory Analysis Tool)来进行可达性分析。

首先找到RedisConn

将dump文件在MAT中打开,然后运行OQL:

select * from redis.clients.jedis.Jedis (RedisConn的实体类)

搜索到一堆Jedis类,然后我们执行

Path To GCRoots->with all references

可以看到如下结果:

redis.clients.jedis.Jedis
|->object
|->item
|->first
|->...
|->java.util.TimerThread
|->internalPool

由此可见,我们的连接仅仅被TimerThread和internalPool(Jedis本身的连接池)持有。所以我们可以判断出大概率是情况2,即忘了归还连接。翻看业务代码:

伪代码
void lock(){
conn = jedis.getResource()
conn.setNx()
// 结束,此处应该有finally{returnResource()}或者采用RedisTemplate
}

最后就是很简单的,业务开发在执行setNx操作后,忘了将连接还回去。导致连接泄露。

如果是情况1如何定位卡住的代码

到此为止,这个问题时解决了。但是如果是情况1的话,我们又该如何分析下去呢?很简单,我们如果找到了jedis被哪个业务线程拥有,直接从heap dump找到其线程号,然后取Jstack中搜索即可知道其卡住的代码栈。

jmap:
redis.clients.jedis.Jedis
|->Thread-123 jstack: Thread-123 prio=...
at xxx.xxx.xxx.blocked

总结

这是一个很简单的问题,知道套路之后排查起来完全不费事。虽然最后排查出来是个很低级的代码,但是这种分析方法值得借鉴。

日常Bug排查-系统失去响应-Redis使用不当的更多相关文章

  1. 日常Bug排查-消息不消费

    日常Bug排查-消息不消费 前言 日常Bug排查系列都是一些简单Bug排查,笔者将在这里介绍一些排查Bug的简单技巧,同时顺便积累素材_. Bug现场 某天下午,在笔者研究某个问题正high的时候.开 ...

  2. 日常Bug排查-抛异常不回滚

    日常Bug排查-抛异常不回滚 前言 日常Bug排查系列都是一些简单Bug排查,笔者将在这里介绍一些排查Bug的简单技巧,同时顺便积累素材_. Bug现场 最近有人反映java应用操作数据库的时候,抛异 ...

  3. 日常Bug排查-Nginx重复请求?

    日常Bug排查-Nginx重复请求? 前言 日常Bug排查系列都是一些简单Bug排查,笔者将在这里介绍一些排查Bug的简单技巧,其中不乏一些看起来很低级但很容易犯的问题. 问题现场 有一天运维突然找到 ...

  4. 如何在win7系统中安装redis

    转载于:http://www.itxuexiwang.com/a/shujukujishu/redis/2016/0216/92.html?1455871954 如何在win7系统中安装redis​ ...

  5. Mac OS使用技巧之十六:系统失去响应怎么办?

    再好的系统,再快的本本,也会在执行时由于种种原因出现卡顿或者死机等失去响应的情况.Mac用户也会时不时碰到这样的情况,最常见的表现为鼠标变为七彩圆圈.通常等上一会儿系统会自己恢复.假设迟迟没有响应的话 ...

  6. 在VMware的Linux系统上安装Redis

    在VMware的Linux系统上安装Redis 具体过程如下: 下载,解压和编译: 在执行make的时候报错,具体报错信息如下: zmalloc.o: In function `zmalloc_use ...

  7. Redis进阶实践之六Redis Desktop Manager连接Windows和Linux系统上的Redis服务

    一.引言 今天本来没有打算写这篇文章,当初我感觉使用这个工具应该很简单,下载的过程也不复杂,也没有打算记录下来.但是在使用的过程中还是出现了一些问题,为了给第一次使用Redis Desktop Man ...

  8. 记一次线上bug排查-quartz线程调度相关

    记一次线上bug排查,与各位共同探讨. 概述:使用quartz做的定时任务,正式生产环境有个任务延迟了1小时之久才触发.在这一小时里各种排查找不出问题,直到延迟时间结束了,该任务才珊珊触发.原因主要就 ...

  9. Redis进阶实践之六Redis Desktop Manager连接Windows和Linux系统上的Redis服务(转载6)

    Redis进阶实践之六Redis Desktop Manager连接Windows和Linux系统上的Redis服务 一.引言 今天本来没有打算写这篇文章,但是,今天测试Redis的时候发现了两个问题 ...

随机推荐

  1. 攻防世界 reverse 进阶 12 ReverseMe-120

    程序流程很清晰 1 int __cdecl main(int argc, const char **argv, const char **envp) 2 { 3 unsigned int v3; // ...

  2. Android Studio 如何运行单个activity

    •写在前面 调试界面运行单个 Activity 可节省编译整个项目的时间提高效率: 本着提高效率的角度,特地上网百度相关知识: •解决方法 首先,在 AndroidManifest.xml 文件中,找 ...

  3. 打造云原生大型分布式监控系统系列文章-腾讯工程师roc

    附上本系列文章链接 打造云原生大型分布式监控系统(一): 大规模场景下 Prometheus 的优化手段 打造云原生大型分布式监控系统(二): Thanos 架构详解 打造云原生大型分布式监控系统(二 ...

  4. 整合一套高性能网关Kong

    前言 相信大家对Api网关都比较的熟悉,我们之前的文章也介绍过ASP.NET Core的网关Ocelot,也介绍过Spring Cloud Gateway.说到网关的主要功能,其实总结起来就两个字&q ...

  5. 一文带你剖析LiteOS互斥锁Mutex源代码

    摘要:多任务环境下会存在多个任务访问同一公共资源的场景,而有些公共资源是非共享的临界资源,只能被独占使用.LiteOS使用互斥锁来避免这种冲突,互斥锁是一种特殊的二值性信号量,用于实现对临界资源的独占 ...

  6. 201871030102-崔红梅 实验二 个人项目—— D{0-1}KP 项目报告

    项目 内容 课程班级博客链接 班级博客 这个作业要求链接 实验二作业链接 我的课程学习目标 1.熟练掌握将本地代码保存至GitHub中2.掌握折扣背包问题3.回顾动态规划算法和回溯算法4.对java语 ...

  7. PAT A1052 Linked List Sorting

    题意:给出N个结点的地址address.数据域data以及指针域next,然后给出链表的首地址,要求把在这个链表上的结点按data值从小到大输出.样例解释:按照输入,这条链表是这样的(结点格式为[ad ...

  8. Sentinel上生产环境只差一步,监控数据持久化

    之前介绍了Sentinel相关的文章,小伙伴在生产实践中不知道有没有这个疑问?我们的Sentinel控制台监控的数据只能看最近5分钟的,如图 那么就导致历史数据是查看不了的,那肯定是不行的,在生产环境 ...

  9. 刨死你系列——手撕ArrayList

    不多BB,直接上代码: public class MyArrayList { //创建数组对象 private Object[] elements; //已使用数组长度 private int siz ...

  10. 使用defineProperty实现自定义setter, 简化前端Angular的重构工作

    一.问题场景 Angular的双向绑定给我们开发提供了很大的遍历,将父scope的引用变量作为参数传递给子指令,这样就可以方便的在父作用域内进行业务操作,数据变更会自动传递到子指令.但是如果你基于一个 ...