记录一次并发情况下的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安装图文教程(Windows和Linux)

    Redis安装图文教程(Windows和Linux)

    这篇文章主要介绍了Redis安装教程(Windows和Linux),本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-03-03
  • Redis 在真实世界的 5 个用法

    Redis 在真实世界的 5 个用法

    Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API这篇文章主要介绍了Redis 在真实世界的 5 个用法,需要的朋友可以参考下
    2018-03-03
  • Redis如何使用乐观锁(CAS)保证数据一致性

    Redis如何使用乐观锁(CAS)保证数据一致性

    本文主要介绍了Redis如何使用乐观锁(CAS)保证数据一致性,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • Redis和Lua使用过程中遇到的小问题

    Redis和Lua使用过程中遇到的小问题

    这篇文章主要给大家介绍了关于Redis和Lua使用过程中遇到的小问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-11-11
  • 使用 Redis 流实现消息队列的代码

    使用 Redis 流实现消息队列的代码

    这篇文章主要介绍了使用 Redis 流实现消息队列,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-11-11
  • Redis shake实现可视化监控的示例代码

    Redis shake实现可视化监控的示例代码

    Redis可视化监控是通过监控Redis服务器的各项指标和状态,并将其以可视化的方式展示给用户,本文给大家介绍了Redis shake实现可视化监控,并通过代码示例讲解的非常详细,需要的朋友可以参考下
    2024-03-03
  • 基于Redis实现每日登录失败次数限制

    基于Redis实现每日登录失败次数限制

    这篇文章主要介绍了通过redis实现每日登录失败次数限制的问题,通过redis记录登录失败的次数,以用户的username为key,本文给出了实例代码,需要的朋友可以参考下
    2019-08-08
  • Redis多种内存淘汰策略及配置技巧分享

    Redis多种内存淘汰策略及配置技巧分享

    本文介绍了 Redis 内存满时的淘汰机制,包括内存淘汰机制的概念,Redis 提供的 8 种淘汰策略(如 noeviction、volatile-lru 等)及其适用场景,还讲解了如何配置淘汰机制,通过合理配置可提高缓存效率和系统性能,需要的朋友可以参考下
    2025-01-01
  • redis分布式锁的8大坑总结梳理

    redis分布式锁的8大坑总结梳理

    这篇文章主要介绍了redis分布式锁的8大坑总结梳理,使用redis的分布式锁,我们首先想到的可能是setNx命令,文章围绕setNx命令展开详细的内容介绍,感兴趣的小伙伴可以参考一下
    2022-07-07
  • redis服务如何启动

    redis服务如何启动

    这篇文章主要介绍了redis服务如何启动问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-08-08

最新评论