(*^_^*)静一静 2025-11-20 14:52 采纳率: 18.8%
浏览 9

redis链接不稳定

问题描述,自己在linux上搭建的一个redis单实例,发现程序连接上去后,运行偶尔会报这个错误,但是又不是必现的,重启应用程序后运行就会恢复,然后运行了几个案例又会报这个错误:


org.springframework.data.redis.RedisSystemException: Redis exception; nested exception is io.lettuce.core.RedisException: java.io.IOException: 远程主机强迫关闭了一个现有的连接。
    at org.springframework.data.redis.connection.lettuce.LettuceExceptionConverter.convert(LettuceExceptionConverter.java:74)
    at org.springframework.data.redis.connection.lettuce.LettuceExceptionConverter.convert(LettuceExceptionConverter.java:41)
    at org.springframework.data.redis.PassThroughExceptionTranslationStrategy.translate(PassThroughExceptionTranslationStrategy.java:44)
    at org.springframework.data.redis.FallbackExceptionTranslationStrategy.translate(FallbackExceptionTranslationStrategy.java:42)
    at org.springframework.data.redis.connection.lettuce.LettuceConnection.convertLettuceAccessException(LettuceConnection.java:272)
    at org.springframework.data.redis.connection.lettuce.LettuceConnection.await(LettuceConnection.java:1063)
    at org.springframework.data.redis.connection.lettuce.LettuceConnection.lambda$doInvoke$4(LettuceConnection.java:920)
    at org.springframework.data.redis.connection.lettuce.LettuceInvoker$Synchronizer.invoke(LettuceInvoker.java:665)
    at org.springframework.data.redis.connection.lettuce.LettuceInvoker.just(LettuceInvoker.java:109)
    at org.springframework.data.redis.connection.lettuce.LettuceHashCommands.hGet(LettuceHashCommands.java:114)
    at org.springframework.data.redis.connection.DefaultedRedisConnection.hGet(DefaultedRedisConnection.java:1359)
    at org.springframework.data.redis.connection.DefaultStringRedisConnection.hGet(DefaultStringRedisConnection.java:540)
    at org.springframework.data.redis.core.DefaultHashOperations.lambda$get$0(DefaultHashOperations.java:55)
    at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:223)
    at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:190)
    at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:97)
    at org.springframework.data.redis.core.DefaultHashOperations.get(DefaultHashOperations.java:55)
    at com.xm.cashloan.core.service.sys.impl.SysConfigServiceImpl.findByCode(SysConfigServiceImpl.java:30)
    at com.xm.cashloan.core.service.sys.impl.SysConfigServiceImpl$$FastClassBySpringCGLIB$$13b580a.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy.invokeMethod(CglibAopProxy.java:386)
    at org.springframework.aop.framework.CglibAopProxy.access$000(CglibAopProxy.java:85)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:704)
    at com.xm.cashloan.core.service.sys.impl.SysConfigServiceImpl$$EnhancerBySpringCGLIB$$9fcebead.findByCode(<generated>)
    at com.xm.cashloan.api.service.SmsService.check(SmsService.java:103)
    at com.xm.cashloan.api.service.SmsService.SendSms(SmsService.java:62)
    at com.xm.cashloan.api.controller.SmsController.sendSms(SmsController.java:58)
    at com.xm.cashloan.api.controller.SmsController$$FastClassBySpringCGLIB$$84115536.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
    at org.springframework.validation.beanvalidation.MethodValidationInterceptor.invoke(MethodValidationInterceptor.java:123)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708)
    at com.xm.cashloan.api.controller.SmsController$$EnhancerBySpringCGLIB$$ece47f88.sendSms(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1071)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:964)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:696)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:779)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:96)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1789)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
    at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)
Caused by: io.lettuce.core.RedisException: java.io.IOException: 远程主机强迫关闭了一个现有的连接。
    at io.lettuce.core.internal.Exceptions.bubble(Exceptions.java:83)
    at io.lettuce.core.internal.Futures.awaitOrCancel(Futures.java:250)
    at io.lettuce.core.LettuceFutures.awaitOrCancel(LettuceFutures.java:74)
    at org.springframework.data.redis.connection.lettuce.LettuceConnection.await(LettuceConnection.java:1061)
    ... 85 more
Caused by: java.io.IOException: 远程主机强迫关闭了一个现有的连接。
    at sun.nio.ch.SocketDispatcher.read0(Native Method)
    at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:43)
    at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)
    at sun.nio.ch.IOUtil.read(IOUtil.java:192)
    at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:380)
    at io.netty.buffer.PooledByteBuf.setBytes(PooledByteBuf.java:259)
    at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:1132)
    at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:357)
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:151)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    ... 1 more
  • 写回答

3条回答 默认 最新

  • 檀越@新空间 2025-11-20 15:09
    关注

    下午好🌅🌅🌅
    本答案参考通义千问

    你遇到的 Redis连接不稳定 问题,是一个比较常见的场景。从错误信息来看:

    io.lettuce.core.RedisException: java.io.IOException: 远程主机强迫关闭了一个现有的连接。
    

    这表明 Redis客户端(如Lettuce)与Redis服务端之间的连接被意外中断,可能的原因包括网络波动、Redis服务器异常、客户端配置不当等。


    🔍 一、可能原因分析

    1. 网络问题

      • Redis服务端和客户端之间存在网络波动或防火墙规则变化。
      • 防火墙/安全组设置导致连接被强制断开。
    2. Redis服务端问题

      • Redis服务重启或宕机。
      • Redis配置不当,例如超时设置过短。
    3. 客户端连接池配置不合理

      • Lettuce连接池未正确配置,导致连接复用失败。
      • 没有设置合理的重试机制或连接超时时间。
    4. 应用代码中没有处理连接异常

      • 程序在连接失败后没有进行重试或重新连接操作。

    🛠 二、解决方案(有序列表)

    1. 检查网络稳定性

    • 确认Redis服务器IP和端口是否可达

      telnet <redis-host> 6379
      

      如果无法连接,说明网络不通,需要排查网络问题。

    • 检查防火墙规则

      sudo ufw status
      sudo iptables -L -n
      

      确保Redis的端口(默认6379)是开放的。

    • 使用ping测试网络延迟

      ping <redis-host>
      

    2. 优化Redis配置(redis.conf

    • 调整超时参数(建议值):

      timeout 300     # 客户端空闲超时时间(单位:秒)
      maxmemory-policy noeviction  # 避免内存不足时自动删除数据
      
    • 启用requirepass并确保客户端使用密码连接,避免未授权访问。


    3. 优化Lettuce连接池配置(Spring Boot)

    application.ymlapplication.properties 中添加以下配置:

    spring:
      redis:
        lettuce:
          pool:
            max-active: 100
            max-idle: 50
            min-idle: 10
            max-wait: 1000ms
            test-while-idle: true
            test-on-borrow: false
            test-on-return: false
          connect-timeout: 5000ms
          command-timeout: 10000ms
    

    重点:
    connect-timeoutcommand-timeout 设置合理值,防止连接长时间阻塞。


    4. 增加异常重试机制

    可以在业务逻辑中对Redis操作进行重试,比如使用 Spring Retry

    添加依赖(Maven):

    <dependency>
        <groupId>org.springframework.retry</groupId>
        <artifactId>spring-retry</artifactId>
        <version>1.2.5.RELEASE</version>
    </dependency>
    

    启用重试:

    @EnableRetry
    @Configuration
    public class RedisConfig {
    }
    

    在方法上添加重试注解:

    @Retryable(maxAttempts = 3, backoff = @Backoff(delay = 1000))
    public String getFromRedis(String key) {
        return redisTemplate.opsForValue().get(key);
    }
    

    重点:
    通过重试机制缓解偶发性连接异常,提升系统容错能力。


    5. 监控Redis连接状态

    使用如下命令查看Redis连接情况:

    redis-cli info | grep connected_clients
    

    如果发现连接数频繁上升或下降,可能是客户端连接未释放。


    6. 升级Lettuce版本

    某些旧版本的Lettuce可能存在连接管理问题,建议升级到最新稳定版:

    <!-- Maven 示例 -->
    <dependency>
        <groupId>io.lettuce</groupId>
        <artifactId>lettuce-core</artifactId>
        <version>6.2.4</version>
    </dependency>
    

    ✅ 三、总结

    | 问题点 | 解决方案 | |--------|----------| | 网络问题 | 检查网络连通性和防火墙设置 | | Redis配置 | 调整超时、内存策略等 | | 连接池配置 | 增加连接池大小和超时设置 | | 异常处理 | 使用Spring Retry实现重试机制 | | 监控 | 查看Redis连接数和日志 | | 版本升级 | 升级Lettuce到最新版本 |


    💡 四、示例:修改后的Redis配置(Spring Boot)

    spring:
      redis:
        host: 127.0.0.1
        port: 6379
        password: yourpassword
        lettuce:
          pool:
            max-active: 100
            max-idle: 50
            min-idle: 10
            max-wait: 1000ms
            test-while-idle: true
          connect-timeout: 5000ms
          command-timeout: 10000ms
    

    如果你能提供更详细的Redis配置文件内容或Spring Boot配置,我可以进一步帮你定位具体问题。希望这些方案能帮助你解决Redis连接不稳定的问题!

    评论

报告相同问题?

问题事件

  • 创建了问题 11月20日