Spring redis使用报错Read timed out排查解决
作者:mmseoamin日期:2023-12-25

文章目录

    • 使用场景
    • 报错信息
    • 解决方式

      使用场景

      • 我们使用redis作为缓存服务,缓存一些业务数据,如路口点位信息、渠化信息、设备信息等
      • 有一些需要实时计算的数据,缓存在redis里,如实时信号周期相位、周期内过车数量等
      • 有需要不同服务访问的数据,使用redis作为共同可访问操作的缓存空间

        报错信息

        • 在数据库数据变动时,需要清楚redis里的缓存,等下次查询需要时从数据库查询,再写入redis
        • 此时删除数据报错,核心报错信息Read timed out,连接超时

          Spring redis使用报错Read timed out排查解决,在这里插入图片描述,第1张

        • 检查了下,redis服务正常
        • 具体报错信息,分两个时间点的报错,(截取部分)如下:
        • 报错日志一JedisConnectionException:
          2023-03-29 10:54:38.186 ERROR 9136 --- [ntainer#7-0-C-1] c.n.r.service.IntersectionQueryService   : Exception in getIntersectionById() with cause = 'redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: Read timed out' and exception = 'java.net.SocketTimeoutException: Read timed out; nested exception is redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: Read timed out'
          org.springframework.data.redis.RedisConnectionFailureException: java.net.SocketTimeoutException: Read timed out; nested exception is redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: Read timed out
          	at org.springframework.data.redis.connection.jedis.JedisExceptionConverter.convert(JedisExceptionConverter.java:65)
          	at org.springframework.data.redis.connection.jedis.JedisExceptionConverter.convert(JedisExceptionConverter.java:42)
          	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.jedis.JedisConnection.convertJedisAccessException(JedisConnection.java:187)
          	at org.springframework.data.redis.connection.jedis.JedisConnection.doWithJedis(JedisConnection.java:802)
          
          • 报错日志二 Error while validating pooled Jedis object:
            2023-08-24 09:44:23.721 ERROR 92250 --- [ns-pool-evictor] redis.clients.jedis.JedisFactory         : Error while validating pooled Jedis object.
            redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: Read timed out
            	at redis.clients.jedis.util.RedisInputStream.ensureFill(RedisInputStream.java:205)
            	at redis.clients.jedis.util.RedisInputStream.readByte(RedisInputStream.java:43)
            	at redis.clients.jedis.Protocol.process(Protocol.java:162)
            	at redis.clients.jedis.Protocol.read(Protocol.java:227)
            	at redis.clients.jedis.Connection.readProtocolWithCheckingBroken(Connection.java:352)
            	at redis.clients.jedis.Connection.getStatusCodeReply(Connection.java:270)
            	at redis.clients.jedis.BinaryJedis.ping(BinaryJedis.java:380)
            	at redis.clients.jedis.JedisFactory.validateObject(JedisFactory.java:214)
            	at org.apache.commons.pool2.impl.GenericObjectPool.evict(GenericObjectPool.java:745)
            	at org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor.run(BaseGenericObjectPool.java:160)
            

            解决方式

            • 报错信息很明显,“Read timed out”超时错误,通常会有以下几种可能:
            • 1、Redis服务端问题导致无法连接或连接出现问题,可以通过检查Redis服务端日志或查看Redis服务器状态来确认
              • Redis未正常在运行,异常终止,或者启动失败
              • 未正确在程序里配置连接ip端口参数,例如ip错误使用localhost,又不在一台机器上
              • 2、 网络连接不稳定或延迟导致Redis连接超时。可以尝试更改网络环境或增加Redis客户端连接超时时间
                • 检查程序服务于redis之间的网络是否联通,是否存在明显延迟
                • 可以修改Spring redis配置参数,增加连接超时时间
                  1. Redis服务器负载过高或使用Redis的其他应用程序占用了太多的资源,导致Redis无法响应请求。可以通过检查Redis服务器的负载或性能参数来确定是否存在此问题。
                  • 检查服务器情况,确保内存和磁盘空间充足,检查已使用内存、剩余内存、已使用磁盘、剩余磁盘等
                  • 简单来说,你的服务对redis的使用频率,如果读写很高很频繁、数据内容很多,就提供比较好的服务器,或者搭建redis集群
                  • 也可以优化Spring redis配置参数,增加最大线程数、空闲线程数、连接超时时间等
                    1. 应用程序本身存在性能瓶颈或异常,导致Redis的操作时间过长。可以检查应用程序代码和运行日志,查找可能导致性能问题的因素
                    • 如果比较大的集合对象在redis存取,会占用很多内存,高并发情况下,可能做不到及时响应,可以只缓存必要的字段属性
                    • 大量的key值,同时加到redis里面,又在一段时间后同时失效,造成瞬时压力过大,这要在业务上做一些随机失效时间
                    • 针对以上情况,我们可以使用不同的解决方法来解决问题。例如,可以优化Redis服务器的配置和设置,更改Redis客户端连接超时时间,或调整应用程序性能等。
                    • 我们此次检查后的改动如下:
                      spring:
                        redis:
                          jedis:
                            pool:
                              min-idle: 10
                              max-idle: 300  # 改大了
                              max-wait: 30000  # 改大了
                              max-active: 200  # 改大了
                      
                      • 对应到我们的docker-compose.yml为
                          core-app:
                            image: june
                            container_name: core
                            volumes:
                              - /etc/localtime:/etc/localtime
                            depends_on:
                              - postgresql
                              - redis
                            environment:
                              - _JAVA_OPTIONS=-Xmx6G -Xms1G
                              - SERVER_PORT=8181
                              - SPRING_PROFILES_ACTIVE=prod,api-docs,no-liquibase
                              - SPRING_DATASOURCE_URL=jdbc:postgresql://postgresql:5432/core
                              - SPRING_DATASOURCE_USERNAME=xxxx
                              - SPRING_DATASOURCE_PASSWORD=xxxxxxx
                              - SPRING_REDIS_HOST=redis
                              - SPRING_REDIS_PASSWORD=xxxxxxxx
                              - spring_redis_jedis_pool_maxIdle=300 # redis配置
                              - spring_redis_jedis_pool_maxWait=30000
                              - spring_redis_jedis_pool_maxActive=200
                            restart: on-failure