白帝彩云间 2025-12-30 09:12 采纳率: 25%
浏览 4

RedisException: java.io.IOException: Connection reset by peer

应用程序在链接使用redis时,出现 org.springframework.data.redis.RedisSystemException: Redis exception; nested exception is io.lettuce.core.RedisException: java.io.IOException: Connection reset by peer错误,但不是一直有错误,是偶尔会提示这个错误,redis这边能看到日志 Client closed connection
目前的部署方式:redis使用的docker-compose部署的,最开始是一主两从,后面出现这个问题后目前切换成单机版了,还是有这个问题,另外部署环境是纯内网,不存在网络丢包的问题,网上搜索了下, 各种方案都没有解决

img

img

  • 写回答

3条回答 默认 最新

  • 檀越@新空间 2025-12-30 09:13
    关注

    上午好☀️☀️☀️️
    本答案参考通义千问

    你遇到的 RedisException: java.io.IOException: Connection reset by peer 错误,是 Redis 客户端在与 Redis 服务端通信时,服务端主动断开了连接。这种错误通常是由于 Redis 服务端检测到客户端异常、超时、或配置不当导致的。

    根据你的描述,问题不是一直出现,而是偶尔发生,并且已经尝试过从主从架构切换为单机版,但问题依旧存在。这表明问题可能出在 客户端配置、连接池设置、或者 Redis 的某些配置参数 上。


    ✅ 问题原因分析

    1. Redis 连接超时(timeout)

    • Redis 默认的 timeout300 秒(5 分钟)
    • 如果客户端长时间不发送请求,Redis 会主动断开连接。
    • Connection reset by peer 就可能是这个原因。

    2. Lettuce 或 Jedis 客户端未正确处理连接

    • 如果客户端没有正确释放连接或未维护连接池,可能导致 Redis 服务端关闭了连接。

    3. Redis 配置中 maxmemory-policy 设置不当

    • 如果 Redis 内存不足,可能会触发淘汰策略,导致部分连接被重置。

    4. Redis 服务端配置问题

    • tcp-keepalive 设置不合理,导致连接空闲时间过长。
    • repl-timeout 等参数配置不当也可能引发连接中断。

    🔧 解决方案

    1. 调整 Redis 服务端配置

    修改 redis.conf 文件:

    # 增加 TCP 心跳间隔,防止空闲连接被断开
    tcp-keepalive 60
    
    # 增加超时时间(可根据实际需要调整)
    timeout 600
    
    # 确保 maxmemory-policy 不是 noeviction,否则可能导致内存不足
    maxmemory-policy allkeys-lru
    

    说明: tcp-keepalive 控制 Redis 与客户端之间的 TCP 心跳频率,防止因空闲连接被系统断开。


    2. 客户端连接池配置优化(以 Lettuce 为例)

    如果你使用的是 Spring Data Redis + Lettuce,请确保连接池配置合理:

    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder()
            .useSsl(false)
            .commandTimeout(Duration.ofSeconds(5))
            .shutdownTimeout(Duration.ofSeconds(1))
            .build();
    
        RedisStandaloneConfiguration config = new RedisStandaloneConfiguration("127.0.0.1", 6379);
        return new LettuceConnectionFactory(config, clientConfig);
    }
    

    重点: 设置合理的 commandTimeoutshutdownTimeout,避免客户端等待太久后触发超时。


    3. 客户端代码中添加连接健康检查机制

    在每次使用 Redis 前,可以先执行一个简单的命令(如 PING)来验证连接是否正常:

    try {
        String response = stringRedisTemplate.opsForValue().get("testKey");
    } catch (RedisSystemException e) {
        if (e.getMessage().contains("Connection reset by peer")) {
            // 重新初始化连接
            stringRedisTemplate.getConnectionFactory().getConnection().close();
            // 可以在这里重新获取连接
        }
    }
    

    说明: 在异常捕获后,手动关闭并重新创建连接,避免使用已失效的连接。


    4. 使用连接池并设置最大空闲时间

    确保客户端连接池配置了合理的 最大空闲时间,防止连接被 Redis 服务端关闭:

    spring:
      redis:
        lettuce:
          pool:
            max-idle: 10
            min-idle: 2
            max-active: 50
            max-wait: 1000ms
            test-while-idle: true
            time-between-eviction-runs: 30000
    

    说明: test-while-idle: true 会在连接空闲时进行健康检查,避免使用失效的连接。


    5. 检查 Redis 日志中的 Client closed connection

    你提到 Redis 日志中有 Client closed connection,这表示 客户端主动关闭了连接,而不是服务端。因此,可能是以下原因:

    • 客户端代码中出现了异常,导致连接未正确释放。
    • 客户端设置了较短的超时时间,导致连接提前关闭。

    建议: 检查客户端日志,看是否有异常堆栈信息,比如 IOExceptionSocketException 等。


    🛠️ 附加建议

    | 项目 | 说明 | |------|------| | Redis 版本 | 确保使用的是稳定版本(如 6.x),避免使用过旧或有 bug 的版本。 | | Docker 网络配置 | 检查 Docker 网络是否稳定,尤其是多容器间的通信。 | | 防火墙/安全组 | 确保内网环境没有防火墙规则限制 Redis 端口(6379)。 | | 监控工具 | 使用 redis-cli info 查看连接数、内存、命中率等指标,帮助定位问题。 |


    ✅ 总结

    | 问题 | 原因 | 解决方案 | |------|------|----------| | Connection reset by peer | Redis 服务端主动断开连接 | 调整 Redis 配置(如 timeout, tcp-keepalive) | | 客户端异常断开 | 客户端未正确处理连接 | 优化连接池配置,增加健康检查 | | 偶发性错误 | 网络或配置不稳定 | 检查 Redis 日志和客户端日志,排查具体原因 |


    如需进一步帮助,请提供以下信息:

    1. Redis 的版本号;
    2. Spring Boot 的版本;
    3. 客户端使用的 Redis 客户端库(如 Lettuce/Jedis);
    4. 相关的配置文件内容(如 application.yml);
    5. 你能否复现该错误?在什么场景下出现?

    我可以帮你更精准地定位问题!

    评论

报告相同问题?

问题事件

  • 修改了问题 12月30日
  • 修改了问题 12月30日
  • 创建了问题 12月30日