redis链接阻塞,导致程序没有响应

一、场景

1、程序在运行一段时间后,会出现没有响应的情况

2、没有报错

3、websocket消息接收正常

4、http请求正常


二、原因

经过排查,发现是redis链接阻塞导致


三、排查

1、使用 info client 命令查看redis链接统计情况

发现阻塞的链接数有132个

redis链接阻塞,导致程序没有响应_第1张图片


2、使用 client list 命令查看redis链接信息

数据太多,这里只贴一部分

在这里插入图片描述

将内容复制到文本工具,找一下程序所在的服务器是否有阻塞的redis链接

搜索关键字:flags=b

client list 命令详解:http://t.csdn.cn/2MWxo

redis链接阻塞,导致程序没有响应_第2张图片


3、关闭程序,看阻塞的链接是否有所减少

当时忘记截图了,这里使用文字描述

redis链接阻塞,导致程序没有响应_第3张图片

补充:该程序配置的redis链接数正好是6个,与程序关闭后减少的阻塞的链接数一致

至此,可以确认

1、程序所在服务器确实有链接阻塞

2、使链接阻塞的命令是blpop


4、排查使用 blpop 命令的相关代码

最终发现如下代码

@Override
public void run() {
    String key = "redisKey_xxx_xxx_test";
    // 死循环
    while (true) {
        try {
        	// 封装的工具类,这里指定的阻塞时间为:0L,永久阻塞,问题就在这里
			Object o = redisUtil.listPop(key, 0L, TimeUnit.SECONDS);
			if (o != null) {
				......
			}
        } catch (Exception e) {
            logger.error("线程执行出现异常!详情:" + e.getMessage(), e);
        }
    }
}

四、解决

调整线程执行逻辑,使redis链接阻塞时间减少

@Override
public void run() {
    String key = "redisKey_xxx_xxx_test";
    while (true) {
        try {
        	// 获取队列长度,只有队列存在数据才往下走
            if (redisUtil.listGetListSize(key) > 0) {
            	// 封装的工具类,指定阻塞时间为:10秒
                Object o = redisUtil.listPop(key, 10L, TimeUnit.SECONDS);
                if (o != null) {
                    ......
                }
            } else {
                Thread.sleep(1000);
            }
        } catch (Exception e) {
            logger.error("线程执行出现异常!详情:" + e.getMessage(), e);
        }
    }
}

你可能感兴趣的:(Java开发问题,redis,redis,数据库,缓存)