记录一次并发情况下的redis导致服务假死的问题解决

 更新时间:2023年09月26日 14:46:29   作者:简单简单小白  
由于Redis需要依赖于操作系统环境,如果系统资源受限,比如过量的进程在挤占系统资源、系统死锁等情况,本文主要介绍了记录一次并发情况下的redis导致服务假死的问题解决,感兴趣的可以了解一下

问题描述

最近项目在做性能压测,框架使用的是 spring boot 2.1.2 + jedis 2.9.1,80个并发持续压测4-5分钟服务就假死,所有的请求就pending,查看服务日志没有任何异常,查看其它没有使用redis的接口都能正常请求。

查找问题思路

  • 查看了一下redis的连接配置,都是正常够用的

  • 再使用jstack看一下堆栈信息

在这里插入图片描述

发现很多WAITING的线程,再往下看都是redis的getResource方法导致的等待。

  • 查看redis的源码Jedis.java

    @Override
    public void close() {
        if (dataSource != null) {//1
            if (client.isBroken()) {
                this.dataSource.returnBrokenResource(this);
            } else {
                this.dataSource.
                        returnResource(this); // 2
            }
            this.dataSource = null;   // 3
        } else {
            super.close();
        }
    }
  • 分析一下这个代码,client.isBroken()这里默认值是false,连接释放的时候先释放resource 然后再将dataSource置为null,那如果是并发的情况下话,那有可能再下一个线程进来的时候dataSource已经就是null了,在执行第2步的时候dataSource刚好被置为null,那这个时候就无法释放连接了。这个时候我们再看下获取连接的方法。JedisSentinelPool.java

    @Override
    public Jedis getResource() {
        while (true) {
            Jedis jedis = super.getResource();
            jedis.setDataSource(this);  // <-- This line 
            // get a reference because it can change concurrently
            final HostAndPort master = currentHostMaster;
            final HostAndPort connection = new HostAndPort(jedis.getClient().getHost(), jedis.getClient()
                    .getPort());
            if (master.equals(connection)) {
                // connected to the correct master
                return jedis;
            } else {
                returnBrokenResource(jedis);
            }
        }
    }

    这里jedis.setDataSource(this);设置的则为null。

问题解决方案

我查看了一下jedis的github,在issue上有找到有人曾经提出过这样的问题,https://github.com/redis/jedis/issues/1920 ,给出的解决方案是升级jedis的jar包到2.10.2版本以上,换成高版本的以后问题果然就解决了。

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.10.2</version>
</dependency>

这里要注意一下的是jedis的版本跟spring-data-redis的版本是有一个对应关系的。

  • spring-data-redis 2.1.x 对应的jedis版本是2.x.x 版本

  • spring-data-redis 2.2.x 对应的jedis 版本就是3.x版本了

分析升级版本以后的改动

还是看那两个类,看看新版本做了什么改动

    public void close() {
        if (this.dataSource != null) {
            Pool<Jedis> pool = this.dataSource;
            this.dataSource = null;
            if (this.client.isBroken()) {
                pool.returnBrokenResource(this);
            } else {
                pool.returnResource(this);
            }
        } else {
            super.close();
        }
    }

这里很明显的处理方式就是讲dataSource复制给pool,然后用pool去释放资源,这个时候设置dataSource与这个就没有关系了,就不存在释放资源释放不了的情况了。

到此这篇关于记录一次并发情况下的redis导致服务假死的问题解决的文章就介绍到这了,更多相关redis导致服务假死内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:

相关文章

  • 玩转Redis搭建集群之Sentinel详解

    玩转Redis搭建集群之Sentinel详解

    这篇文章主要给大家介绍了关于Redis搭建集群之Sentinel的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-11-11
  • 查看Redis内存信息的命令

    查看Redis内存信息的命令

    Redis 是一个开源、高性能的Key-Value数据库,被广泛应用在服务器各种场景中。本文介绍几个查看Redis内存信息的命令,包括常用的info memory、info keyspace、bigkeys等。
    2020-09-09
  • redis保存AtomicInteger对象踩坑及解决

    redis保存AtomicInteger对象踩坑及解决

    这篇文章主要介绍了redis保存AtomicInteger对象踩坑及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • Redis fork进程分配不到内存解决方案

    Redis fork进程分配不到内存解决方案

    这篇文章主要介绍了Redis fork进程分配不到内存解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11
  • redis如何清理缓存

    redis如何清理缓存

    本文主要介绍了redis如何清理缓存,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-01-01
  • 大白话讲解调用Redis的increment失败原因及推荐使用详解

    大白话讲解调用Redis的increment失败原因及推荐使用详解

    本文主要介绍了调用Redis的increment失败原因及推荐使用,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • Redis教程(八):事务详解

    Redis教程(八):事务详解

    这篇文章主要介绍了Redis教程(八):事务详解,本文讲解了,本文讲解了事务概述、相关命令列表、命令使用示例、WATCH命令和基于CAS的乐观锁等内容,需要的朋友可以参考下
    2015-04-04
  • redis中opsForList().range()的使用方法详解

    redis中opsForList().range()的使用方法详解

    这篇文章主要给大家介绍了关于redis中opsForList().range()的使用方法,文中通过实例代码以及图文介绍的非常详细,对大家学习或者使用redis具有一定的参考学习价值,需要的朋友可以参考下
    2023-03-03
  • Redis解决缓存一致性问题

    Redis解决缓存一致性问题

    本文主要介绍了Redis 解决缓存一致性问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-10-10
  • Redis分布式锁解决秒杀超卖问题

    Redis分布式锁解决秒杀超卖问题

    本文主要介绍了Redis分布式锁解决秒杀超卖问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07

最新评论