记录服务器上,不定时出现io.lettuce.core.RedisCommandTimeoutException: Command timed out after 12 millisecond

记录服务器上,不定时出现io.lettuce.core.RedisCommandTimeoutException: Command timed out after 12 millisecond,第1张

记录服务器上,不定时出现io.lettuce.core.RedisCommandTimeoutException: Command timed out after 12 millisecond(s)
  • 日志

    • org.springframework.data.redis.RedisConnectionFailureException: Unable to connect to Redis; nested exception is org.springframework.data.redis.connection.PoolException: Could not get a resource from the pool; nested exception is io.lettuce.core.RedisConnectionException: Unable to connect to 192.168.10.143:6350
      	at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.translateException(LettuceConnectionFactory.java:1534) ~[spring-data-redis-2.3.5.RELEASE.jar:2.3.5.RELEASE]
      	at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.getConnection(LettuceConnectionFactory.java:1442) ~[spring-data-redis-2.3.5.RELEASE.jar:2.3.5.RELEASE]
      	at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getNativeConnection(LettuceConnectionFactory.java:1228) ~[spring-data-redis-2.3.5.RELEASE.jar:2.3.5.RELEASE]
      	at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getConnection(LettuceConnectionFactory.java:1211) ~[spring-data-redis-2.3.5.RELEASE.jar:2.3.5.RELEASE]
      	at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getSharedReactiveConnection(LettuceConnectionFactory.java:985) ~[spring-data-redis-2.3.5.RELEASE.jar:2.3.5.RELEASE]
      	at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getReactiveConnection(LettuceConnectionFactory.java:446) ~[spring-data-redis-2.3.5.RELEASE.jar:2.3.5.RELEASE]
      	at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getReactiveConnection(LettuceConnectionFactory.java:99) ~[spring-data-redis-2.3.5.RELEASE.jar:2.3.5.RELEASE]
      	at reactor.core.publisher.MonoSupplier.call(MonoSupplier.java:85) ~[reactor-core-3.3.11.RELEASE.jar:3.3.11.RELEASE]
      	at reactor.core.publisher.FluxSubscribeOnCallable$CallableSubscribeOnSubscription.run(FluxSubscribeOnCallable.java:225) ~[reactor-core-3.3.11.RELEASE.jar:3.3.11.RELEASE]
      	at reactor.core.scheduler.SchedulerTask.call(SchedulerTask.java:68) ~[reactor-core-3.3.11.RELEASE.jar:3.3.11.RELEASE]
      	at reactor.core.scheduler.SchedulerTask.call(SchedulerTask.java:28) ~[reactor-core-3.3.11.RELEASE.jar:3.3.11.RELEASE]
      	at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266) ~[na:1.8.0_251]
      	at java.util.concurrent.FutureTask.run(FutureTask.java) ~[na:1.8.0_251]
      	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access1(ScheduledThreadPoolExecutor.java:180) ~[na:1.8.0_251]
      	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[na:1.8.0_251]
      	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_251]
      	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_251]
      	at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_251]
      Caused by: org.springframework.data.redis.connection.PoolException: Could not get a resource from the pool; nested exception is io.lettuce.core.RedisConnectionException: Unable to connect to 192.168.10.143:6350
      	at org.springframework.data.redis.connection.lettuce.LettucePoolingConnectionProvider.getConnection(LettucePoolingConnectionProvider.java:109) ~[spring-data-redis-2.3.5.RELEASE.jar:2.3.5.RELEASE]
      	at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.getConnection(LettuceConnectionFactory.java:1440) ~[spring-data-redis-2.3.5.RELEASE.jar:2.3.5.RELEASE]
      	... 16 common frames omitted
      Caused by: io.lettuce.core.RedisConnectionException: Unable to connect to 192.168.10.143:6350
      	at io.lettuce.core.RedisConnectionException.create(RedisConnectionException.java:78) ~[lettuce-core-5.3.5.RELEASE.jar:5.3.5.RELEASE]
      	at io.lettuce.core.RedisConnectionException.create(RedisConnectionException.java:56) ~[lettuce-core-5.3.5.RELEASE.jar:5.3.5.RELEASE]
      	at io.lettuce.core.AbstractRedisClient.getConnection(AbstractRedisClient.java:242) ~[lettuce-core-5.3.5.RELEASE.jar:5.3.5.RELEASE]
      	at io.lettuce.core.RedisClient.connect(RedisClient.java:206) ~[lettuce-core-5.3.5.RELEASE.jar:5.3.5.RELEASE]
      	at org.springframework.data.redis.connection.lettuce.StandaloneConnectionProvider.lambda$getConnection(StandaloneConnectionProvider.java:115) ~[spring-data-redis-2.3.5.RELEASE.jar:2.3.5.RELEASE]
      	at java.util.Optional.orElseGet(Optional.java:267) ~[na:1.8.0_251]
      	at org.springframework.data.redis.connection.lettuce.StandaloneConnectionProvider.getConnection(StandaloneConnectionProvider.java:115) ~[spring-data-redis-2.3.5.RELEASE.jar:2.3.5.RELEASE]
      	at org.springframework.data.redis.connection.lettuce.LettucePoolingConnectionProvider.lambda$null<(LettucePoolingConnectionProvider.java:97) ~[spring-data-redis-2.3.5.RELEASE.jar:2.3.5.RELEASE]
      	at io.lettuce.core.support.ConnectionPoolSupport$RedisPooledObjectFactory.create(ConnectionPoolSupport.java:211) ~[lettuce-core-5.3.5.RELEASE.jar:5.3.5.RELEASE]
      	at io.lettuce.core.support.ConnectionPoolSupport$RedisPooledObjectFactory.create(ConnectionPoolSupport.java:201) ~[lettuce-core-5.3.5.RELEASE.jar:5.3.5.RELEASE]
      	at org.apache.commons.pool2.BasePooledObjectFactory.makeObject(BasePooledObjectFactory.java:58) ~[commons-pool2-2.8.1.jar:2.8.1]
      	at org.apache.commons.pool2.impl.GenericObjectPool.create(GenericObjectPool.java:899) ~[commons-pool2-2.8.1.jar:2.8.1]
      	at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:429) ~[commons-pool2-2.8.1.jar:2.8.1]
      	at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:354) ~[commons-pool2-2.8.1.jar:2.8.1]
      	at io.lettuce.core.support.ConnectionPoolSupport.borrowObject(ConnectionPoolSupport.java:122) ~[lettuce-core-5.3.5.RELEASE.jar:5.3.5.RELEASE]
      	at io.lettuce.core.support.ConnectionPoolSupport.borrowObject(ConnectionPoolSupport.java:117) ~[lettuce-core-5.3.5.RELEASE.jar:5.3.5.RELEASE]
      	at org.springframework.data.redis.connection.lettuce.LettucePoolingConnectionProvider.getConnection(LettucePoolingConnectionProvider.java:103) ~[spring-data-redis-2.3.5.RELEASE.jar:2.3.5.RELEASE]
      	... 17 common frames omitted
      Caused by: io.lettuce.core.RedisCommandTimeoutException: Command timed out after 12 millisecond(s)
      	at io.lettuce.core.ExceptionFactory.createTimeoutException(ExceptionFactory.java:51) ~[lettuce-core-5.3.5.RELEASE.jar:5.3.5.RELEASE]
      	at io.lettuce.core.protocol.CommandExpiryWriter.lambda$potentiallyExpire<(CommandExpiryWriter.java:172) ~[lettuce-core-5.3.5.RELEASE.jar:5.3.5.RELEASE]
      	at io.netty.util.concurrent.PromiseTask.runTask(PromiseTask.java:98) ~[netty-common-4.1.53.Final.jar:4.1.53.Final]
      	at io.netty.util.concurrent.ScheduledFutureTask.run(ScheduledFutureTask.java:170) ~[netty-common-4.1.53.Final.jar:4.1.53.Final]
      	at io.netty.util.concurrent.DefaultEventExecutor.run(DefaultEventExecutor.java:66) ~[netty-common-4.1.53.Final.jar:4.1.53.Final]
      	at io.netty.util.concurrent.SingleThreadEventExecutor.run(SingleThreadEventExecutor.java:989) ~[netty-common-4.1.53.Final.jar:4.1.53.Final]
      	at io.netty.util.internal.ThreadExecutorMap.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.53.Final.jar:4.1.53.Final]
      	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.53.Final.jar:4.1.53.Final]
      	... 1 common frames omitted
      
      
      
原因分析
  • 由于lettuce没有心跳检测,直接能判断为查询redis数据超时了。

  • 网上百度了一波,发现有结论说是替换lettuce 为 jedis 就能解决问题**【此方案无效】**

    • 修改pom文件

      •     dependency>
              <groupId>org.springframework.bootgroupId>
              <artifactId>spring-boot-starter-data-redis<artifactId>
              <exclusions>
                exclusion>
                  <groupId>redis.clientsgroupId>
                  artifactId>jedis<artifactId>
                <exclusion>
                exclusion>
                  <groupId>io.lettucegroupId>
                  artifactId>lettuce-coreartifactId>
                exclusion>
              <exclusions>
            <dependency>
            dependency>
              <groupId>redis.clientsgroupId>
              artifactId>jedis
      • 前面将redis的连接池从lettuce换成了jedis,但是依然出现了redis超时异常,由此可见应该从配置问题找起。不过首先先定位下报错位置,从错误日志最底部的方法栈排查java.net.SocketInputStream.socketRead0为本地方法,可以从java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
      • artifactId
        >
        Caused by: java.net.SocketTimeoutException: Read timed out at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.socketRead(SocketInputStream.java:116) at java.net.SocketInputStream.read(SocketInputStream.java:171) at java.net.SocketInputStream.read(SocketInputStream.java:141) at java.net.SocketInputStream.read(SocketInputStream.java:127) at redis.clients.jedis.util.RedisInputStream.ensureFill(RedisInputStream.java:199) ... 111 common frames omitted dependency>
  • 替换后,使用jedis链接池运行一段时间,又报出了JedisConnectionException: java.net.SocketTimeoutException: Read timed out异常,接下去继续分析

记录服务器上,不定时出现JedisConnectionException: java.net.SocketTimeoutException: Read timed out的问题 错误日志
  • org.springframework.data.redis.RedisConnectionFailureException: Cannot get Jedis connection; nested exception is redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: Read timed out
    	at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.fetchJedisConnector(JedisConnectionFactory.java:282)
    	at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.getConnection(JedisConnectionFactory.java:476)
    	at org.springframework.data.redis.core.RedisConnectionUtils.doGetConnection(RedisConnectionUtils.java:134)
    	at org.springframework.data.redis.core.RedisConnectionUtils.getConnection(RedisConnectionUtils.java:97)
    	at org.springframework.data.redis.core.RedisConnectionUtils.getConnection(RedisConnectionUtils.java:84)
    	at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:215)
    	at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:188)
    	at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:96)
    	at org.springframework.data.redis.core.DefaultSetOperations.size(DefaultSetOperations.java:330)
    	at com.rivtower.rivus.product.service.impl.ProductDefServiceImpl.handlePublishingQty(ProductDefServiceImpl.java:279)
    	at com.rivtower.rivus.product.service.impl.ProductDefServiceImpl$$FastClassBySpringCGLIB$$e459cf51.invoke()
    	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:687)
    	at com.rivtower.rivus.product.service.impl.ProductDefServiceImpl$$EnhancerBySpringCGLIB$$85b0914f.handlePublishingQty()
    	at com.rivtower.rivus.product.controller.ProductDefController.queryProductDefByRegisterId(ProductDefController.java:85)
    	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:190)
    	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
    	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
    	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878)
    	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792)
    	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
    	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
    	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
    	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:626)
    	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320)
    	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126)
    	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90)
    	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:118)
    	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)
    	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    	at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
    	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    	at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:158)
    	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    	at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
    	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    	at org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationFilter.doFilterInternal(BearerTokenAuthenticationFilter.java:130)
    	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
    	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    	at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92)
    	at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77)
    	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
    	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    	at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
    	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)
    	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
    	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)
    	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
    	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
    	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    	at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:93)
    	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
    	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
    	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
    	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
    	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)
    	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
    	at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:747)
    	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)
    	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
    	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
    	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)
    	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    	at java.lang.Thread.run(Thread.java:748)
    Caused by: 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:155)
    	at redis.clients.jedis.Protocol.read(Protocol.java:220)
    	at redis.clients.jedis.Connection.readProtocolWithCheckingBroken(Connection.java:278)
    	at redis.clients.jedis.Connection.getStatusCodeReply(Connection.java:196)
    	at redis.clients.jedis.BinaryClient.connect(BinaryClient.java:119)
    	at redis.clients.jedis.BinaryJedis.connect(BinaryJedis.java:1904)
    	at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.fetchJedisConnector(JedisConnectionFactory.java:277)
    	... 103 common frames omitted
    Caused by: java.net.SocketTimeoutException: Read timed out
    	at java.net.SocketInputStream.socketRead0(Native Method)
    	at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
    	at java.net.SocketInputStream.read(SocketInputStream.java:171)
    	at java.net.SocketInputStream.read(SocketInputStream.java:141)
    	at java.net.SocketInputStream.read(SocketInputStream.java:127)
    	at redis.clients.jedis.util.RedisInputStream.ensureFill(RedisInputStream.java:199)
    	... 111 common frames omitted
    
问题分析
问题排查
  • 由于排查SocketInputStream这个IO类没有识别性,最终定位错误日志最终在redis.clients.jedis.util.RedisInputStream.ensureFill(RedisInputStream.java:199),

  • 定位代码报错位置

      SocketInputStream
  • 下断点后排查,发现超时时间是SocketInputStream的一个属性,那么就找下这个属性的初始化赋值。

      <
反向推理
  • 方向查询SocketInputStream的初始化创建过程

    • - RedisInputStream( InputStream,int in) < size- .. redis.clients.jedisconnectConnection()<- newRedisInputStream ( .getInputStreamsocket())<- .createSocket jedisSocketFactory()<- DefaultJedisSocketFactory. 	createSocket()@Overridepublic
      
  • 查看createSocket()源码,发现超时时间是 通过getSoTimeout()获取,getSoTimeout()方法获取的是DefaultJedisSocketFactory的属性值soTimeout,那么接下去追溯DefaultJedisSocketFactory创建过程

    •   Socket
        createSocket ( )throwsIOException Socket = {
          null socket ; try=
          new {
            socket Socket ( );.setReuseAddress
            // ->@wjw_add
            socket(true);.setKeepAlive
            socket(true);// Will monitor the TCP connection is// valid .
            setTcpNoDelay
            socket(true);// Socket buffer Whetherclosed, to// ensure timely delivery of data .
            setSoLinger
            socket(true,0) ;// Control calls close () method,// the underlying socket is closed // immediately
            // <-@wjw_add
            .
            connect
      
            socket(newInetSocketAddress( getHost(),getPort( )),getConnectionTimeout( ));//超时时间.
            setSoTimeout
            socket(getSoTimeout());if(
      
            ) ifssl( {
              null ==) = sslSocketFactory( {
                sslSocketFactory SSLSocketFactory )SSLSocketFactory. getDefault();}=
              .
              socket createSocket sslSocketFactory(,getHostsocket( ),getPort( ),true) ;if(
              null !=) ( sslParameters( {
                SSLSocket)). socketsetSSLParameters();sslParameters}if
              (
              ( null!=) && hostnameVerifier(
                  ! .verifyhostnameVerifier(getHost(),(( SSLSocket)). socketgetSession())))String= {
                String message . format("The connection to '%s' failed ssl/tls hostname verification.",
                  getHost( ));thrownew
                JedisConnectionException ( );message}}
              return
            ;
            } socketcatch
          ( Exception )if ex( {
            != nullsocket ) .close {
              socket();}throw
            ;
            } ex}
          DefaultJedisSocketFactory(String host, int port, int connectionTimeout, int soTimeout,
            boolean ssl, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters,
            HostnameVerifier hostnameVerifier) <- setSoTimeout() <-  BinaryJedis(final String host, final int port, final int connectionTimeout,
            final int soTimeout) <- Jedis(final String host, final int port, final int connectionTimeout, final int soTimeout) <-  JedisConnectionFactory.getActiveSentinel()
      
        public
      
  • DefaultJedisSocketFactory创建过程

    • class
  • 在JedisConnectionFactory.getActiveSentinel方法中找到如下逻辑

    • JedisConnectionFactory implements InitializingBean , DisposableBean, RedisConnectionFactoryprivate final {
          
          JedisClientConfiguration ; private clientConfigurationJedis
          
      	getActiveSentinel ( )Assert. {
      
      		isTrue(RedisConfiguration.isSentinelConfiguration(),configuration"SentinelConfig must not be null!") ;for(
      
      		RedisNode :( node ( SentinelConfiguration)). configurationgetSentinels())//创建JedisJedis {
      			=
      			new jedis Jedis ( .getHostnode(),.getPort node(),getConnectTimeout( ),getReadTimeout( ));tryif
      
      			( {
      				. pingjedis().equalsIgnoreCase("pong"))potentiallySetClientName( {
      
      					);jedisreturn;
      					} jedis}
      				catch
      			( Exception ). exwarn {
      				log(String.format("Ping failed for sentinel host:%s",.getHost node()),); ex}}
      			throw
      		new
      
      		InvalidDataAccessResourceUsageException ( "No Sentinel found");}private
      	int
      
      	getReadTimeout ( )returnMath {
      		. toIntExact(.getReadTimeoutclientConfiguration().toMillis());}}
      	package
      .
      
    • 可以看到,readTimeOut最终是获取了JedisClientConfiguration clientConfiguration。接下去还是一样,查询JedisClientConfiguration的初始化赋值过程

  • 下断点排查是通过public JedisConnectionFactory(RedisStandaloneConfiguration standaloneConfig, JedisClientConfiguration clientConfig) 构造方法初始化的 JedisConnectionFactory。而在此构造方法中传入了 JedisClientConfiguration clientConfig,这个类的具体实现类是 DefaultJedisClientConfiguration,这里可以发现已经是排查到spring-data-redis模块了,接下去可以提前设想下,这个Configuration类 读取的配置 是读取 yml文件或者config文件的配置。

    • . org.springframework.data.redis;connectionclassjedisDefaultJedisClientConfiguration
      
      implements JedisClientConfiguration DefaultJedisClientConfiguration ( {
      	boolean,@Nullable useSslSSLSocketFactory , @Nullable sslSocketFactorySSLParameters
      			, @Nullable sslParametersHostnameVerifier , boolean hostnameVerifier, @Nullable usePoolingGenericObjectPoolConfig
      			, @Nullable poolConfigString , Duration clientName, Duration readTimeout)
      			this connectTimeout. {
      
      		=;useSsl this useSsl.
      		=OptionalsslSocketFactory . ofNullable();sslSocketFactorythis.
      		=OptionalsslParameters . ofNullable();sslParametersthis.
      		=OptionalhostnameVerifier . ofNullable();hostnameVerifierthis.
      		=;usePooling this usePooling.
      		=OptionalpoolConfig . ofNullable();poolConfigthis.
      		=OptionalclientName . ofNullable();clientNamethis.
      		=;readTimeout this readTimeout.
      		=;connectTimeout } connectTimeout}
      	public
      interface
      
  • 继续追溯org.springframework.data.redis.connection.jedis.DefaultJedisClientConfiguration 初始化过程

    • JedisClientConfiguration private Duration {
          = Duration readTimeout . ofMillis(Protocol.);DEFAULT_TIMEOUT@Overridepublic
          
          JedisClientConfigurationBuilder
          readTimeout ( Duration)Assert readTimeout. {
      
              notNull(,"Duration must not be null!"readTimeout) ;this.
      
              =;readTimeout return readTimeoutthis
              ; }@Override
          public
      
          JedisClientConfiguration
          build ( )returnnew {
      
              DefaultJedisClientConfiguration ( ,,useSsl, sslSocketFactory, sslParameters, hostnameVerifier, usePooling, poolConfig, clientName) readTimeout; connectTimeout}}
          package
      .
      
      
      
  • 最终找到了 spring-data-redis-starter的自动装配的类

    • . org.springframework.boot.autoconfigure;dataimportredis.
      
      . javaUnknownHostExceptionnet;import.
      . javaDurationtime;import.
      
      . org.apache.commons.pool2GenericObjectPoolimpl;import.
      . redis.clientsJedisjedis;import.
      . redis.clientsJedisPoolConfigjedis;import.
      
      . org.springframework.beansObjectProviderfactory;import.
      . org.springframework.boot.autoconfigureConditionalOnClasscondition;import.
      . org.springframework.boot.autoconfigureConditionalOnMissingBeancondition;import.
      . org.springframework.contextBeanannotation;import.
      . org.springframework.contextConfigurationannotation;import.
      . org.springframework.data.redisRedisClusterConfigurationconnection;import.
      . org.springframework.data.redisRedisConnectionFactoryconnection;import.
      . org.springframework.data.redisRedisSentinelConfigurationconnection;import.
      . org.springframework.data.redis.connectionJedisClientConfigurationjedis;import.
      . org.springframework.data.redis.connectionJedisClientConfigurationjedis.JedisClientConfigurationBuilder;import.
      . org.springframework.data.redis.connectionJedisConnectionjedis;import.
      . org.springframework.data.redis.connectionJedisConnectionFactoryjedis;import.
      . org.springframeworkStringUtilsutil;/**
       * Redis connection configuration using Jedis.
       *
       * @author Mark Paluch
       * @author Stephane Nicoll
       */@Configuration
      
      (
      =falseproxyBeanMethods ) @ConditionalOnClass(
      GenericObjectPool.{ class,JedisConnection. class,Jedis. class}) classJedisConnectionConfiguration
      extends RedisConnectionConfiguration JedisConnectionConfiguration ( {
      
      	RedisProperties,ObjectProvider properties<
      			RedisSentinelConfiguration,ObjectProvider> sentinelConfiguration<
      			RedisClusterConfiguration)super> clusterConfiguration( {
      		,,properties) sentinelConfiguration; clusterConfiguration}@Bean
      	@ConditionalOnMissingBean
      
      	(
      	RedisConnectionFactory.class)JedisConnectionFactoryredisConnectionFactory
      	( ObjectProvider<
      			JedisClientConfigurationBuilderCustomizer)throws> builderCustomizersUnknownHostException return createJedisConnectionFactory {
      		( );builderCustomizers}private
      	JedisConnectionFactory
      
      	createJedisConnectionFactory ( ObjectProvider<
      			JedisClientConfigurationBuilderCustomizer)JedisClientConfiguration> builderCustomizers= {
      		getJedisClientConfiguration clientConfiguration ( );builderCustomizersif(
      		getSentinelConfig ()!=null ) returnnew {
      			JedisConnectionFactory ( getSentinelConfig(),); clientConfiguration}if
      		(
      		getClusterConfiguration ()!=null ) returnnew {
      			JedisConnectionFactory ( getClusterConfiguration(),); clientConfiguration}return
      		new
      		JedisConnectionFactory ( getStandaloneConfig(),); clientConfiguration}private
      	JedisClientConfiguration
      
      	getJedisClientConfiguration ( ObjectProvider<
      			JedisClientConfigurationBuilderCustomizer)JedisClientConfigurationBuilder> builderCustomizers= {
      		applyProperties builder ( JedisClientConfiguration.builder());.=
      		RedisPropertiesgetPropertiesPool pool ( ).getJedis().getPool();if(
      		!= nullpool ) applyPooling( {
      			,)pool; builder}if
      		(
      		StringUtils .hasText(getProperties().getUrl()))customizeConfigurationFromUrl( {
      			);builder}.
      		orderedStream
      		builderCustomizers().forEach(().customizercustomize -> customizer())builder;return.
      		build builder();}private
      	JedisClientConfigurationBuilder
      
      	applyProperties ( JedisClientConfigurationBuilder)if builder( {
      		getProperties ().isSsl()).useSsl {
      			builder();}if
      		(
      		getProperties ().getTimeout()!=null ) Duration= {
      			getProperties timeout ( ).getTimeout();.readTimeout
      			builder().timeoutconnectTimeout();timeout}if
      		(
      		StringUtils .hasText(getProperties().getClientName())).clientName {
      			builder(getProperties().getClientName());}return
      		;
      		} builderprivate
      	void
      
      	applyPooling ( .,RedisProperties.Pool pool)
      			JedisClientConfiguration.JedisClientConfigurationBuilder builderusePooling {
      		builder().poolConfig(jedisPoolConfig())pool;}private
      	JedisPoolConfig
      
      	jedisPoolConfig ( .)RedisPropertiesJedisPoolConfigPool pool= {
      		new config JedisPoolConfig ( );.setMaxTotal
      		config(.getMaxActivepool());.setMaxIdle
      		config(.getMaxIdlepool());.setMinIdle
      		config(.getMinIdlepool());if(
      		. getTimeBetweenEvictionRunspool()!=null ) .setTimeBetweenEvictionRunsMillis {
      			config(.getTimeBetweenEvictionRunspool().toMillis());}if
      		(
      		. getMaxWaitpool()!=null ) .setMaxWaitMillis {
      			config(.getMaxWaitpool().toMillis());}return
      		;
      		} configprivate
      	void
      
      	customizeConfigurationFromUrl ( .)JedisClientConfigurationConnectionInfoJedisClientConfigurationBuilder builder= {
      		parseUrl connectionInfo ( getProperties().getUrl());if(
      		. isUseSslconnectionInfo()).useSsl {
      			builder();}}
      		}
      	
    • @ConfigurationProperties
    • (
    • ="spring.redis"prefix ) publicclass
      RedisProperties /**
          * Database index used by the connection factory.
          */ private {
      
         int
         = 0 database ; /**
          * Connection URL. Overrides host, port, and password. User is ignored. Example:
          * redis://user:password@example.com:6379
          */private
      
         String
         ; /**
          * Redis server host.
          */ urlprivate
      
         String
         = "localhost" host ; /**
          * Login password of the redis server.
          */private
      
         String
         ; /**
          * Redis server port.
          */ passwordprivate
      
         int
         = 6379 port ; /**
          * Whether to enable SSL support.
          */private
      
         boolean
         ; /**
          * Connection timeout.
          */ sslprivate
      
         Duration
         ; /**
          * Client name to be set on connections with CLIENT SETNAME.
          */ timeoutprivate
      
         String
         ; private clientNameSentinel
      
         ; private sentinelCluster
      
         ; private clusterfinal
      
         Jedis = new jedis Jedis ( );privatefinal
      
         Lettuce = new lettuce Lettuce ( );publicint
      
         getDatabase ( )returnthis {
            . ;}databasepublic
         void
      
         setDatabase ( int)this database. {
            =;database } databasepublic
         String
      
         getUrl ( )returnthis {
            . ;}urlpublic
         void
      
         setUrl ( String)this url. {
            =;url } urlpublic
         String
      
         getHost ( )returnthis {
            . ;}hostpublic
         void
      
         setHost ( String)this host. {
            =;host } hostpublic
         String
      
         getPassword ( )returnthis {
            . ;}passwordpublic
         void
      
         setPassword ( String)this password. {
            =;password } passwordpublic
         int
      
         getPort ( )returnthis {
            . ;}portpublic
         void
      
         setPort ( int)this port. {
            =;port } portpublic
         boolean
      
         isSsl ( )returnthis {
            . ;}sslpublic
         void
      
         setSsl ( boolean)this ssl. {
            =;ssl } sslpublic
         void
      
         setTimeout ( Duration)this timeout. {
            =;timeout } timeoutpublic
         Duration
      
         getTimeout ( )returnthis {
            . ;}timeoutpublic
         String
      
         getClientName ( )returnthis {
            . ;}clientNamepublic
         void
      
         setClientName ( String)this clientName. {
            =;clientName } clientNamepublic
         Sentinel
      
         getSentinel ( )returnthis {
            . ;}sentinelpublic
         void
      
         setSentinel ( Sentinel)this sentinel. {
            =;sentinel } sentinelpublic
         Cluster
      
         getCluster ( )returnthis {
            . ;}clusterpublic
         void
      
         setCluster ( Cluster)this cluster. {
            =;cluster } clusterpublic
         Jedis
      
         getJedis ( )returnthis {
            . ;}jedispublic
         Lettuce
      
         getLettuce ( )returnthis {
            . ;}lettuce/**
          * Pool properties.
          */
         public
      
         static
         class Pool /**
             * Maximum number of "idle" connections in the pool. Use a negative value to
             * indicate an unlimited number of idle connections.
             */ private {
      
            int
            = 8 maxIdle ; /**
             * Target for the minimum number of idle connections to maintain in the pool. This
             * setting only has an effect if both it and time between eviction runs are
             * positive.
             */private
      
            int
            = 0 minIdle ; /**
             * Maximum number of connections that can be allocated by the pool at a given
             * time. Use a negative value for no limit.
             */private
      
            int
            = 8 maxActive ; /**
             * Maximum amount of time a connection allocation should block before throwing an
             * exception when the pool is exhausted. Use a negative value to block
             * indefinitely.
             */private
      
            Duration
            = Duration maxWait . ofMillis(-1);/**
             * Time between runs of the idle object evictor thread. When positive, the idle
             * object evictor thread starts, otherwise no idle object eviction is performed.
             */private
      
            Duration
            ; public timeBetweenEvictionRunsint
      
            getMaxIdle ( )returnthis {
               . ;}maxIdlepublic
            void
      
            setMaxIdle ( int)this maxIdle. {
               =;maxIdle } maxIdlepublic
            int
      
            getMinIdle ( )returnthis {
               . ;}minIdlepublic
            void
      
            setMinIdle ( int)this minIdle. {
               =;minIdle } minIdlepublic
            int
      
            getMaxActive ( )returnthis {
               . ;}maxActivepublic
            void
      
            setMaxActive ( int)this maxActive. {
               =;maxActive } maxActivepublic
            Duration
      
            getMaxWait ( )returnthis {
               . ;}maxWaitpublic
            void
      
            setMaxWait ( Duration)this maxWait. {
               =;maxWait } maxWaitpublic
            Duration
      
            getTimeBetweenEvictionRuns ( )returnthis {
               . ;}timeBetweenEvictionRunspublic
            void
      
            setTimeBetweenEvictionRuns ( Duration)this timeBetweenEvictionRuns. {
               =;timeBetweenEvictionRuns } timeBetweenEvictionRuns}
            /**
          * Cluster properties.
          */
      
         public
      
         static
         class Cluster /**
             * Comma-separated list of "host:port" pairs to bootstrap from. This represents an
             * "initial" list of cluster nodes and is required to have at least one entry.
             */ private {
      
            List
            < String;/**
             * Maximum number of redirects to follow when executing commands across the
             * cluster.
             */> nodesprivate
      
            Integer
            ; public maxRedirectsList
      
            < StringgetNodes(> )returnthis {
               . ;}nodespublic
            void
      
            setNodes ( List<String)this> nodes. {
               =;nodes } nodespublic
            Integer
      
            getMaxRedirects ( )returnthis {
               . ;}maxRedirectspublic
            void
      
            setMaxRedirects ( Integer)this maxRedirects. {
               =;maxRedirects } maxRedirects}
            /**
          * Redis sentinel properties.
          */
      
         public
      
         static
         class Sentinel /**
             * Name of the Redis server.
             */ private {
      
            String
            ; /**
             * Comma-separated list of "host:port" pairs.
             */ masterprivate
      
            List
            < String;/**
             * Password for authenticating with sentinel(s).
             */> nodesprivate
      
            String
            ; public passwordString
      
            getMaster ( )returnthis {
               . ;}masterpublic
            void
      
            setMaster ( String)this master. {
               =;master } masterpublic
            List
      
            < StringgetNodes(> )returnthis {
               . ;}nodespublic
            void
      
            setNodes ( List<String)this> nodes. {
               =;nodes } nodespublic
            String
      
            getPassword ( )returnthis {
               . ;}passwordpublic
            void
      
            setPassword ( String)this password. {
               =;password } password}
            /**
          * Jedis client properties.
          */
      
         public
      
         static
         class Jedis /**
             * Jedis pool configuration.
             */ private {
      
            Pool
            ; public poolPool
      
            getPool ( )returnthis {
               . ;}poolpublic
            void
      
            setPool ( Pool)this pool. {
               =;pool } pool}
            /**
          * Lettuce client properties.
          */
      
         public
      
         static
         class Lettuce /**
             * Shutdown timeout.
             */ private {
      
            Duration
            = Duration shutdownTimeout . ofMillis(100);/**
             * Lettuce pool configuration.
             */private
      
            Pool
            ; private poolfinal
      
            Cluster = new cluster Cluster ( );publicDuration
      
            getShutdownTimeout ( )returnthis {
               . ;}shutdownTimeoutpublic
            void
      
            setShutdownTimeout ( Duration)this shutdownTimeout. {
               =;shutdownTimeout } shutdownTimeoutpublic
            Pool
      
            getPool ( )returnthis {
               . ;}poolpublic
            void
      
            setPool ( Pool)this pool. {
               =;pool } poolpublic
            Cluster
      
            getCluster ( )returnthis {
               . ;}clusterpublic
            static
      
            class Cluster private final {
      
               Refresh = new refresh Refresh ( );publicRefresh
      
               getRefresh ( )returnthis {
                  . ;}refreshpublic
               static
      
               class Refresh /**
                   * Cluster topology refresh period.
                   */ private {
      
                  Duration
                  ; /**
                   * Whether adaptive topology refreshing using all available refresh
                   * triggers should be used.
                   */ periodprivate
      
                  boolean
                  ; public adaptiveDuration
      
                  getPeriod ( )returnthis {
                     . ;}periodpublic
                  void
      
                  setPeriod ( Duration)this period. {
                     =;period } periodpublic
                  boolean
      
                  isAdaptive ( )returnthis {
                     . ;}adaptivepublic
                  void
      
                  setAdaptive ( boolean)this adaptive. {
                     =;adaptive } adaptive}
                  }
      
               }
      
            }
      
         //1.存在类存在属性依赖RedisTemplate,这就开始了Redis相关类bean的初始化
      
      public
      
  • 总结最后发现RedisInputStream的readTimeout的值,是从RedisProperties 配置类中获取的,获取的配置项是spring.redis.timeout

正向总结-逻辑
  1. 项目类依赖于RedisTemplate

    • class
      Test @Autowired private{
      	RedisTemplate
      	< String,String;}> redisTemplate@Configuration
      @EnableCaching
      
  2. RedisTemplate由项目中配置类创建Bean,此处决定RedisTemplate的初始化创建依赖于RedisConnectionFactory factory

    • //开启注解
      public class
      RedisConfig extends CachingConfigurerSupport @Resource ( {
        ="customObjectMapper"name ) privateObjectMapper
        ; /**
         * redisTemplate相关配置
         * @param factory
         * @return
         */ om@Bean
      
        public
        RedisTemplate
        < String,ObjectredisTemplate (> RedisConnectionFactory)RedisTemplate factory< {
      
          String,Object= new> template RedisTemplate < ()>;// 配置连接工厂.
          setConnectionFactory
          template();factory//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)Jackson2JsonRedisSerializer
      
          <
          Object=new> jacksonSerial Jackson2JsonRedisSerializer < (Object>.class);.setObjectMapper
      
          jacksonSerial();om// 值采用json序列化.
      
          setValueSerializer
          template();jacksonSerial//使用StringRedisSerializer来序列化和反序列化redis的key值.
          setKeySerializer
          template(newStringRedisSerializer( ));// 设置hash key 和value序列化模式.
      
          setHashKeySerializer
          template(newStringRedisSerializer( ));.setHashValueSerializer
          template();jacksonSerial.afterPropertiesSet
          template();return;
      
          } template}
        package
      
      
      .
      
  3. RedisConnectionFactory 的创建是由org.springframework.boot.autoconfigure.data.redis.JedisConnectionConfiguration创建的。这里需要记住JedisConnectionConfiguration下的两个属性,因为JedisConnectionConfiguration是继承RedisConnectionConfiguration,在RedisConnectionConfiguration中存在属性 private final RedisProperties properties;后续会用到

    • . org.springframework.boot.autoconfigure;data/**
       * Redis connection configuration using Jedis.
       *
       * @author Mark Paluch
       * @author Stephane Nicoll
       */redis@Configuration
      (
      =falseproxyBeanMethods ) @ConditionalOnClass(
      GenericObjectPool.{ class,JedisConnection. class,Jedis. class}) classJedisConnectionConfiguration
      extends RedisConnectionConfiguration JedisConnectionConfiguration ( {
      
      	RedisProperties,ObjectProvider properties<
      			RedisSentinelConfiguration,ObjectProvider> sentinelConfiguration<
      			RedisClusterConfiguration)super> clusterConfiguration( {
      		,,properties) sentinelConfiguration; clusterConfiguration}//当项目中不存在RedisConnectionFactory,则创建RedisConnectionFactory
      	@Bean
      
          @ConditionalOnMissingBean
      	(
      	RedisConnectionFactory.class)JedisConnectionFactoryredisConnectionFactory
      	( ObjectProvider<
      			JedisClientConfigurationBuilderCustomizer)throws> builderCustomizersUnknownHostException return createJedisConnectionFactory {
              //调用私有方法createJedisConnectionFactory(ObjectProvider builderCustomizers)
      		( );builderCustomizers}private
      	JedisConnectionFactory
      
      	createJedisConnectionFactory ( ObjectProvider<
      			JedisClientConfigurationBuilderCustomizer)JedisClientConfiguration> builderCustomizers= {
      		getJedisClientConfiguration clientConfiguration ( );builderCustomizersif(
      		getSentinelConfig ()!=null ) returnnew {
      			JedisConnectionFactory ( getSentinelConfig(),); clientConfiguration}if
      		(
      		getClusterConfiguration ()!=null ) returnnew {
      			JedisConnectionFactory ( getClusterConfiguration(),); clientConfiguration}return
      		new
      		JedisConnectionFactory ( getStandaloneConfig(),); clientConfiguration}private
      	JedisClientConfiguration
      
      	getJedisClientConfiguration ( ObjectProvider<
      			JedisClientConfigurationBuilderCustomizer)JedisClientConfigurationBuilder> builderCustomizers= {
      		applyProperties builder ( JedisClientConfiguration.builder());.=
      		RedisPropertiesgetPropertiesPool pool ( ).getJedis().getPool();if(
      		!= nullpool ) applyPooling( {
      			,)pool; builder}if
      		(
      		StringUtils .hasText(getProperties().getUrl()))customizeConfigurationFromUrl( {
      			);builder}.
      		orderedStream
      		builderCustomizers().forEach(().customizercustomize -> customizer())builder;return.
      		build builder();}private
      	JedisClientConfigurationBuilder
      
      	applyProperties ( JedisClientConfigurationBuilder)if builder( {
      		getProperties ().isSsl()).useSsl {
      			builder();}if
      		(
      		getProperties ().getTimeout()!=null ) Duration= {
      			getProperties timeout ( ).getTimeout();.readTimeout
      			builder().timeoutconnectTimeout();timeout}if
      		(
      		StringUtils .hasText(getProperties().getClientName())).clientName {
      			builder(getProperties().getClientName());}return
      		;
      		} builderprivate
      	void
      
      	applyPooling ( .,RedisProperties.Pool pool)
      			JedisClientConfiguration.JedisClientConfigurationBuilder builderusePooling {
      		builder().poolConfig(jedisPoolConfig())pool;}private
      	JedisPoolConfig
      
      	jedisPoolConfig ( .)RedisPropertiesJedisPoolConfigPool pool= {
      		new config JedisPoolConfig ( );.setMaxTotal
      		config(.getMaxActivepool());.setMaxIdle
      		config(.getMaxIdlepool());.setMinIdle
      		config(.getMinIdlepool());if(
      		. getTimeBetweenEvictionRunspool()!=null ) .setTimeBetweenEvictionRunsMillis {
      			config(.getTimeBetweenEvictionRunspool().toMillis());}if
      		(
      		. getMaxWaitpool()!=null ) .setMaxWaitMillis {
      			config(.getMaxWaitpool().toMillis());}return
      		;
      		} configprivate
      	void
      
      	customizeConfigurationFromUrl ( .)JedisClientConfigurationConnectionInfoJedisClientConfigurationBuilder builder= {
      		parseUrl connectionInfo ( getProperties().getUrl());if(
      		. isUseSslconnectionInfo()).useSsl {
      			builder();}}
      		}
      	abstract
      
      class
      
    • RedisConnectionConfiguration private final {
      
      	RedisProperties ; } properties@ConfigurationProperties
      (
      
  4. 而从JedisConnectionConfiguration(RedisProperties properties,
    ObjectProvider sentinelConfiguration,
    ObjectProvider clusterConfiguration)可以看到,JedisConnectionConfiguration依赖RedisProperties配置类

    • ="spring.redis"prefix ) publicclass
      RedisProperties /**
      	 * Database index used by the connection factory.
      	 */ private {
      
      	int
      	= 0 database ; /**
      	 * Connection URL. Overrides host, port, and password. User is ignored. Example:
      	 * redis://user:password@example.com:6379
      	 */private
      
      	String
      	; /**
      	 * Redis server host.
      	 */ urlprivate
      
      	String
      	= "localhost" host ; /**
      	 * Login password of the redis server.
      	 */private
      
      	String
      	; /**
      	 * Redis server port.
      	 */ passwordprivate
      
      	int
      	= 6379 port ; /**
      	 * Whether to enable SSL support.
      	 */private
      
      	boolean
      	; /**
      	 * Connection timeout.
      	 */ sslprivate
      
      	Duration
      	; /**
      	 * Client name to be set on connections with CLIENT SETNAME.
      	 */ timeoutprivate
      
      	String
      	; private clientNameSentinel
      
      	; private sentinelCluster
      
      	; private clusterfinal
      
      	Jedis = new jedis Jedis ( );privatefinal
      
      	Lettuce = new lettuce Lettuce ( );publicint
      
      	getDatabase ( )returnthis {
      		. ;}databasepublic
      	void
      
      	setDatabase ( int)this database. {
      		=;database } databasepublic
      	String
      
      	getUrl ( )returnthis {
      		. ;}urlpublic
      	void
      
      	setUrl ( String)this url. {
      		=;url } urlpublic
      	String
      
      	getHost ( )returnthis {
      		. ;}hostpublic
      	void
      
      	setHost ( String)this host. {
      		=;host } hostpublic
      	String
      
      	getPassword ( )returnthis {
      		. ;}passwordpublic
      	void
      
      	setPassword ( String)this password. {
      		=;password } passwordpublic
      	int
      
      	getPort ( )returnthis {
      		. ;}portpublic
      	void
      
      	setPort ( int)this port. {
      		=;port } portpublic
      	boolean
      
      	isSsl ( )returnthis {
      		. ;}sslpublic
      	void
      
      	setSsl ( boolean)this ssl. {
      		=;ssl } sslpublic
      	void
      
      	setTimeout ( Duration)this timeout. {
      		=;timeout } timeoutpublic
      	Duration
      
      	getTimeout ( )returnthis {
      		. ;}timeoutpublic
      	String
      
      	getClientName ( )returnthis {
      		. ;}clientNamepublic
      	void
      
      	setClientName ( String)this clientName. {
      		=;clientName } clientNamepublic
      	Sentinel
      
      	getSentinel ( )returnthis {
      		. ;}sentinelpublic
      	void
      
      	setSentinel ( Sentinel)this sentinel. {
      		=;sentinel } sentinelpublic
      	Cluster
      
      	getCluster ( )returnthis {
      		. ;}clusterpublic
      	void
      
      	setCluster ( Cluster)this cluster. {
      		=;cluster } clusterpublic
      	Jedis
      
      	getJedis ( )returnthis {
      		. ;}jedispublic
      	Lettuce
      
      	getLettuce ( )returnthis {
      		. ;}lettuce/**
      	 * Pool properties.
      	 */
      	public
      
      	static
      	class Pool /**
      		 * Maximum number of "idle" connections in the pool. Use a negative value to
      		 * indicate an unlimited number of idle connections.
      		 */ private {
      
      		int
      		= 8 maxIdle ; /**
      		 * Target for the minimum number of idle connections to maintain in the pool. This
      		 * setting only has an effect if both it and time between eviction runs are
      		 * positive.
      		 */private
      
      		int
      		= 0 minIdle ; /**
      		 * Maximum number of connections that can be allocated by the pool at a given
      		 * time. Use a negative value for no limit.
      		 */private
      
      		int
      		= 8 maxActive ; /**
      		 * Maximum amount of time a connection allocation should block before throwing an
      		 * exception when the pool is exhausted. Use a negative value to block
      		 * indefinitely.
      		 */private
      
      		Duration
      		= Duration maxWait . ofMillis(-1);/**
      		 * Time between runs of the idle object evictor thread. When positive, the idle
      		 * object evictor thread starts, otherwise no idle object eviction is performed.
      		 */private
      
      		Duration
      		; public timeBetweenEvictionRunsint
      
      		getMaxIdle ( )returnthis {
      			. ;}maxIdlepublic
      		void
      
      		setMaxIdle ( int)this maxIdle. {
      			=;maxIdle } maxIdlepublic
      		int
      
      		getMinIdle ( )returnthis {
      			. ;}minIdlepublic
      		void
      
      		setMinIdle ( int)this minIdle. {
      			=;minIdle } minIdlepublic
      		int
      
      		getMaxActive ( )returnthis {
      			. ;}maxActivepublic
      		void
      
      		setMaxActive ( int)this maxActive. {
      			=;maxActive } maxActivepublic
      		Duration
      
      		getMaxWait ( )returnthis {
      			. ;}maxWaitpublic
      		void
      
      		setMaxWait ( Duration)this maxWait. {
      			=;maxWait } maxWaitpublic
      		Duration
      
      		getTimeBetweenEvictionRuns ( )returnthis {
      			. ;}timeBetweenEvictionRunspublic
      		void
      
      		setTimeBetweenEvictionRuns ( Duration)this timeBetweenEvictionRuns. {
      			=;timeBetweenEvictionRuns } timeBetweenEvictionRuns}
      		/**
      	 * Cluster properties.
      	 */
      
      	public
      
      	static
      	class Cluster /**
      		 * Comma-separated list of "host:port" pairs to bootstrap from. This represents an
      		 * "initial" list of cluster nodes and is required to have at least one entry.
      		 */ private {
      
      		List
      		< String;/**
      		 * Maximum number of redirects to follow when executing commands across the
      		 * cluster.
      		 */> nodesprivate
      
      		Integer
      		; public maxRedirectsList
      
      		< StringgetNodes(> )returnthis {
      			. ;}nodespublic
      		void
      
      		setNodes ( List<String)this> nodes. {
      			=;nodes } nodespublic
      		Integer
      
      		getMaxRedirects ( )returnthis {
      			. ;}maxRedirectspublic
      		void
      
      		setMaxRedirects ( Integer)this maxRedirects. {
      			=;maxRedirects } maxRedirects}
      		/**
      	 * Redis sentinel properties.
      	 */
      
      	public
      
      	static
      	class Sentinel /**
      		 * Name of the Redis server.
      		 */ private {
      
      		String
      		; /**
      		 * Comma-separated list of "host:port" pairs.
      		 */ masterprivate
      
      		List
      		< String;/**
      		 * Password for authenticating with sentinel(s).
      		 */> nodesprivate
      
      		String
      		; public passwordString
      
      		getMaster ( )returnthis {
      			. ;}masterpublic
      		void
      
      		setMaster ( String)this master. {
      			=;master } masterpublic
      		List
      
      		< StringgetNodes(> )returnthis {
      			. ;}nodespublic
      		void
      
      		setNodes ( List<String)this> nodes. {
      			=;nodes } nodespublic
      		String
      
      		getPassword ( )returnthis {
      			. ;}passwordpublic
      		void
      
      		setPassword ( String)this password. {
      			=;password } password}
      		/**
      	 * Jedis client properties.
      	 */
      
      	public
      
      	static
      	class Jedis /**
      		 * Jedis pool configuration.
      		 */ private {
      
      		Pool
      		; public poolPool
      
      		getPool ( )returnthis {
      			. ;}poolpublic
      		void
      
      		setPool ( Pool)this pool. {
      			=;pool } pool}
      		/**
      	 * Lettuce client properties.
      	 */
      
      	public
      
      	static
      	class Lettuce /**
      		 * Shutdown timeout.
      		 */ private {
      
      		Duration
      		= Duration shutdownTimeout . ofMillis(100);/**
      		 * Lettuce pool configuration.
      		 */private
      
      		Pool
      		; private poolfinal
      
      		Cluster = new cluster Cluster ( );publicDuration
      
      		getShutdownTimeout ( )returnthis {
      			. ;}shutdownTimeoutpublic
      		void
      
      		setShutdownTimeout ( Duration)this shutdownTimeout. {
      			=;shutdownTimeout } shutdownTimeoutpublic
      		Pool
      
      		getPool ( )returnthis {
      			. ;}poolpublic
      		void
      
      		setPool ( Pool)this pool. {
      			=;pool } poolpublic
      		Cluster
      
      		getCluster ( )returnthis {
      			. ;}clusterpublic
      		static
      
      		class Cluster private final {
      
      			Refresh = new refresh Refresh ( );publicRefresh
      
      			getRefresh ( )returnthis {
      				. ;}refreshpublic
      			static
      
      			class Refresh /**
      				 * Cluster topology refresh period.
      				 */ private {
      
      				Duration
      				; /**
      				 * Whether adaptive topology refreshing using all available refresh
      				 * triggers should be used.
      				 */ periodprivate
      
      				boolean
      				; public adaptiveDuration
      
      				getPeriod ( )returnthis {
      					. ;}periodpublic
      				void
      
      				setPeriod ( Duration)this period. {
      					=;period } periodpublic
      				boolean
      
      				isAdaptive ( )returnthis {
      					. ;}adaptivepublic
      				void
      
      				setAdaptive ( boolean)this adaptive. {
      					=;adaptive } adaptive}
      				}
      
      			}
      
      		}
      
      	redis
      
      :
      
  5. RedisProperties配置类获取的是从配置类中获取spring.redis 下的相关配置项

    1.  database:
          4host :
          port: 192.168.10.143
          6350password :
          lettuce:
          pool:
            max-idle:
              8max-active :
              8min-idle :
              0max-wait :
              -1timeout :
          12@Bean @ConditionalOnMissingBean
      
  6. 上一步为初始化JedisConnectionConfiguration及其相关的依赖配置类,接下去的步骤是初始化JedisConnectionFactory类 的bean,通过JedisConnectionConfiguration.createJedisConnectionFactory() 方法

    • 	(
      	RedisConnectionFactory.class)JedisConnectionFactoryredisConnectionFactory
      	( ObjectProvider<
      			JedisClientConfigurationBuilderCustomizer)throws> builderCustomizersUnknownHostException return createJedisConnectionFactory {
      		( );builderCustomizers}//创建JedisConnectionFactory
      	private
      
      	JedisConnectionFactory
      	createJedisConnectionFactory ( ObjectProvider<
      			JedisClientConfigurationBuilderCustomizer)//获取JedisClientConfigurationBuilder> builderCustomizersJedisClientConfiguration {
              =
      		getJedisClientConfiguration clientConfiguration ( );builderCustomizersif(
      		getSentinelConfig ()!=null ) returnnew {
      			JedisConnectionFactory ( getSentinelConfig(),); clientConfiguration}if
      		(
      		getClusterConfiguration ()!=null ) returnnew {
      			JedisConnectionFactory ( getClusterConfiguration(),); clientConfiguration}return
      		new
      		JedisConnectionFactory ( getStandaloneConfig(),); clientConfiguration}//获取JedisClientConfigurationBuilder
      	private
      
          JedisClientConfiguration
      	getJedisClientConfiguration ( ObjectProvider<
      			JedisClientConfigurationBuilderCustomizer)//  org.springframework.data.redis.connection.jedis.JedisClientConfiguration.DefaultJedisClientConfigurationBuilder> builderCustomizers//关键步骤调用applyProperties 将redisProperties的timeout属性值 赋值给builder的readTimeout字段 {
              JedisClientConfigurationBuilder
              =
      		applyProperties builder ( JedisClientConfiguration.builder());.=
      		RedisPropertiesgetPropertiesPool pool ( ).getJedis().getPool();if(
      		!= nullpool ) applyPooling( {
      			,)pool; builder}if
      		(
      		StringUtils .hasText(getProperties().getUrl()))customizeConfigurationFromUrl( {
      			);builder}.
      		orderedStream
      		builderCustomizers().forEach(().customizercustomize -> customizer())builder;//Build the {@link JedisClientConfiguration} with the configuration applied from this builder. 这里要注意的是readTimeout的赋值return
              .
      		build builder();}private
      	JedisClientConfigurationBuilder
      	
      	applyProperties ( JedisClientConfigurationBuilder)if builder( 	{
      		getProperties ().isSsl()).useSsl {
      			builder();}//此处设置了redis readTimeout
      		if
              (
      		getProperties ().getTimeout()!=null ) //获取的是RedisProperties的Timeout属性Duration {
                  =
      			getProperties timeout ( ).getTimeout();.readTimeout
      			builder().timeoutconnectTimeout();timeout}if
      		(
      		StringUtils .hasText(getProperties().getClientName())).clientName {
      			builder(getProperties().getClientName());}return
      		;
      		} builderclass
      	DefaultJedisClientConfigurationBuilder
      
      
      
      	implements JedisClientConfigurationBuilder , JedisPoolingClientConfigurationBuilder,
      			JedisSslClientConfigurationBuilder//初始化默认为Protocol.DEFAULT_TIMEOUT public static final int DEFAULT_TIMEOUT = 2000; private {
          	
              Duration
      		= Duration readTimeout . ofMillis(Protocol.);DEFAULT_TIMEOUT/*
      		 * (non-Javadoc)
      		 * @see org.springframework.data.redis.connection.jedis.JedisClientConfiguration.JedisClientConfigurationBuilder#build()
      		 */@Override
      		public
      		JedisClientConfiguration
      		build ( )returnnew {
      
      			DefaultJedisClientConfiguration ( ,,useSsl, sslSocketFactory, sslParameters, hostnameVerifier, usePooling,
      					poolConfig, clientName) readTimeout; connectTimeout}/*
      		 * (non-Javadoc)
      		 * @see org.springframework.data.redis.connection.jedis.JedisClientConfiguration.JedisClientConfigurationBuilder#readTimeout(java.time.Duration)
      		 */
      		@Override
              
              
      		public
      		JedisClientConfigurationBuilder
      		readTimeout ( Duration)Assert readTimeout. {
      
      			notNull(,"Duration must not be null!"readTimeout) ;this.
      
      			=;readTimeout return readTimeoutthis
      			; }}
      		
    • 初始化JedisConnectionFactory类 的bean
    • 调用getJedisClientConfiguration()方法生成JedisClientConfigurationBuilder对象
  7. 此处可以获得到逻辑

    1. 生成JedisClientConfigurationBuilder对象后,调用applyProperties(JedisClientConfigurationBuilder builder)方法,将redisProperties的timeout属性值,赋值给JedisClientConfigurationBuilder 的ReadTimeout属性
    2. 总结:由此框架就定义了redis的readTimeout时间,至此在createJedisConnectionFactory()方法中的getJedisClientConfiguration()逻辑结束了。
    3. privateJedisConnectionFactory
  8. 将生成的JedisClientConfiguration赋值给JedisConnectionFactory,最后返回JedisConnectionFactory

    • 	createJedisConnectionFactory ( ObjectProvider<
      			JedisClientConfigurationBuilderCustomizer)JedisClientConfiguration> builderCustomizers= {
      		getJedisClientConfiguration clientConfiguration ( );builderCustomizersif(
      		getSentinelConfig ()!=null ) returnnew {
      			JedisConnectionFactory ( getSentinelConfig(),); clientConfiguration}if
      		(
      		getClusterConfiguration ()!=null ) returnnew {
      			JedisConnectionFactory ( getClusterConfiguration(),); clientConfiguration}return
      		new
      		JedisConnectionFactory ( getStandaloneConfig(),); clientConfiguration}@Bean
      	public
      
  9. 创建完JedisConnectionFactory类的Bean对象后,回到redisTemplate类的Bean创建方法中,通过setConnectionFactory() 给redisTemplate赋值redis工厂。最后,完成redisTemplate 类的Bean创建。

    •   RedisTemplate
        < String,ObjectredisTemplate (> RedisConnectionFactory)RedisTemplate factory< {
      
          String,Object= new> template RedisTemplate < ()>;// 配置连接工厂.
          setConnectionFactory
          template();factory//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)Jackson2JsonRedisSerializer
      
          <
          Object=new> jacksonSerial Jackson2JsonRedisSerializer < (Object>.class);.setObjectMapper
      
          jacksonSerial();om// 值采用json序列化.
      
          setValueSerializer
          template();jacksonSerial//使用StringRedisSerializer来序列化和反序列化redis的key值.
          setKeySerializer
          template(newStringRedisSerializer( ));// 设置hash key 和value序列化模式.
      
          setHashKeySerializer
          template(newStringRedisSerializer( ));.setHashValueSerializer
          template();jacksonSerial.afterPropertiesSet
          template();return;
      
          } template.
        opsForValue
      
      
  10. 接下去是调用流程

    • redisTemplate().get();keypublicclass
      
    • RedisTemplate < K,Vextends RedisAccessor> implements RedisOperations < K,V, BeanClassLoaderAware>AbstractOperations ( {
          
          RedisTemplate<K,V) this> template. {
      		=;template } templateDefaultValueOperations
      	(
          
          RedisTemplate<K,V) super> template( {
      		);template}private
      	final
          
          ValueOperations < K,V= new> valueOps DefaultValueOperations < (this>);/*
      	 * (non-Javadoc)
      	 * @see org.springframework.data.redis.core.RedisOperations#opsForValue()
      	 */@Override
          
      	public
      	ValueOperations
      	< K,VopsForValue (> )return; {
      		} valueOps@Nullable
      	public
          
          <
      	T Texecute> ( RedisCallback<T,boolean> action) return exposeConnectionexecute {
      		( ,,actionfalse exposeConnection) ;}@Nullable
      	public
          
          <
      	T Texecute> ( RedisCallback<T,boolean> action, boolean exposeConnection) Assert pipeline. {
      
      		isTrue(,"template not initialized; call afterPropertiesSet() before using it"initialized) ;Assert.
      		notNull(,"Callback object must not be null"action) ;RedisConnectionFactory=
      
      		getRequiredConnectionFactory factory ( );RedisConnection=
      		null conn ; tryif
      		( {
      
      			) // only bind resources in case of potential transaction synchronizationenableTransactionSupport= {
      				RedisConnectionUtils
      				conn . bindConnection(,)factory; enableTransactionSupport}else
      			= RedisConnectionUtils {
      				conn . getConnection();factory}boolean
      			=
      
      			TransactionSynchronizationManager existingConnection . hasResource();factoryRedisConnection=
      
      			preProcessConnection connToUse ( ,)conn; existingConnectionboolean=
      
      			. pipelineStatus isPipelined connToUse();if(
      			&& !pipeline ) .pipelineStatusopenPipeline {
      				connToUse();}RedisConnection
      			=
      
      			( connToExpose ? :exposeConnection createRedisConnectionProxy connToUse ( ))connToUse;T=
      			. result doInRedis action();connToExpose// close pipelineif
      
      			(
      			&& !pipeline ) .pipelineStatusclosePipeline {
      				connToUse();}// TODO: any other connection processing?
      			return
      
      			postProcessResult
      			( ,,result) connToUse; existingConnection}finally
      		RedisConnectionUtils . {
      			releaseConnection(,,conn) factory; enableTransactionSupport}}
      		}
      	class
      DefaultValueOperations
      
    • < K,Vextends AbstractOperations> < K,Vimplements ValueOperations> < K,VDefaultValueOperations (> {
      
      	RedisTemplate<K,V) super> template( {
      		);template}@Nullable
      	<
      
          	T
      	Texecute> ( RedisCallback<T,boolean> callback) return exposeConnection. {
      		execute template(,)callback; exposeConnection}/*
      	 * redis get 命令
      	 */
      	@Override
          
      	public
      	V
      	get ( Object)return keyexecute {
      
      		( newValueDeserializingRedisCallback( )@Overridekeyprotected {
      
      			byte
      			[ ]inRedis( byte[],RedisConnection rawKey) return connection. {
      				get connection();rawKey}}
      			,
      		true) ;}}
      	public
      abstract
      
    • class RedisConnectionUtils public static {
      	RedisConnection getConnection ( RedisConnectionFactory)return factorygetConnection {
      		( ,falsefactory) ;}public
      	static
          
          RedisConnection getConnection ( RedisConnectionFactory,boolean factory) return transactionSupportdoGetConnection {
      		( ,truefactory, false, ); transactionSupport}public
      	static
          
          RedisConnection doGetConnection ( RedisConnectionFactory,boolean factory, boolean allowCreate, boolean bind)
      			Assert transactionSupport. {
      
      		notNull(,"No RedisConnectionFactory specified"factory) ;RedisConnectionHolder=
      
      		( connHolder RedisConnectionHolder )TransactionSynchronizationManager. getResource();factoryif(
      
      		!= nullconnHolder ) if( {
      			) potentiallyRegisterTransactionSynchronisationtransactionSupport( {
      				,)connHolder; factory}return
      			.
      			getConnection connHolder();}if
      		(
      
      		! )throwallowCreatenew {
      			IllegalArgumentException ( "No connection found and allowCreate = false");}if
      		(
      
      		. isDebugEnabledlog()).debug {
      			log("Opening RedisConnection");}//获取 RedisConnection
      		RedisConnection
      
              =
      		. conn getConnection factory();if(
      
      		) RedisConnectionbind= {
      
      			; connectionToBind if conn(
      			&& isActualNonReadonlyTransactionActivetransactionSupport ( ))=createConnectionProxy {
      				connectionToBind ( ,)conn; factory}=
      			new
      
      			connHolder RedisConnectionHolder ( );connectionToBindTransactionSynchronizationManager.
      
      			bindResource(,)factory; connHolderif(
      			) potentiallyRegisterTransactionSynchronisationtransactionSupport( {
      				,)connHolder; factory}return
      			.
      
      			getConnection connHolder();}return
      		;
      
      		} conn}
      	public
      class
      
    • JedisConnectionFactory implements InitializingBean , DisposableBean, RedisConnectionFactory/*
      	 * (non-Javadoc)
      	 * @see org.springframework.data.redis.connection.RedisConnectionFactory#getConnection()
      	 */ public {
      	
      	RedisConnection
      	getConnection ( )if( {
      
      		isRedisClusterAware ())returngetClusterConnection {
      			( );}//获取redis 连接
      		Jedis
      		=
      		fetchJedisConnector jedis ( );JedisConnection=
      		( connection getUsePool ()?new JedisConnection ( ,,jedisgetDatabase pool( ),getClientName( )):new
      				JedisConnection ( ,nulljedis, getDatabase( ),getClientName( )));.setConvertPipelineAndTxResults
      		connection();convertPipelineAndTxResultsreturnpostProcessConnection
      		( );connection}protected
      	Jedis
          
          fetchJedisConnector ( )tryif {
      		( {
      
      			getUsePool ()&&!= null pool ) return. {
      				getResource pool();}Jedis
      			=
      
      			createJedis jedis ( );//强制初始化,这里会获取连接// force initialization (see Jedis issue #82)
                  .
      			connect
      			jedis();potentiallySetClientName(
      
      			);jedisreturn;
      			} jediscatch
      		( Exception )throw exnew {
      			RedisConnectionFailureException ( "Cannot get Jedis connection",); ex}}
      		}
      	public
      class
      
    • BinaryJedis implements BasicCommands , BinaryJedisCommands, MultiKeyBinaryCommands, AdvancedBinaryJedisCommands,
          BinaryScriptingCommands, Closeablepublic void {
        connect ( ).connect {
          client();}public
        class
      BinaryClient extends Connection @Override public {
          	void
            connect ( )if( {
              ! isConnected())super. {
                connect();if(
                != nulluser ) auth( {
                  ,)user; passwordgetStatusCodeReply(
                  );}else
                if ( != nullpassword ) auth( {
                  );passwordgetStatusCodeReply(
                  );}if
                (
                0 )db > select( {
                  );dbgetStatusCodeReply(
                  );}}
                }
              }
            }
          public
      class
      
      
      
    • Connection implements Closeable public String {
            getStatusCodeReply ( )flush( {
              );finalbyte
              [ ]=( resp byte [])readProtocolWithCheckingBroken( );if(
              null ==) return respnull {
                ; }else
              return SafeEncoder {
                . encode();resp}}
              protected
            Object
         	  readProtocolWithCheckingBroken ( )if( {
              ) throwbrokennew {
                JedisConnectionException ( "Attempting to read from a broken connection");}try
              return
      
              Protocol {
                . read();inputStream}catch
              ( JedisConnectionException )= exctrue {
                broken ; throw;
                } exc}
              }
            public
      final
      
    • class Protocol public static {
      	Object read ( finalRedisInputStream) return isprocess {
          	( );is}private
        	static
          Object process ( finalRedisInputStream) final isbyte {
              = . b readByte is();switch(
              ) caseb: {
              return PLUS_BYTEprocessStatusCodeReply
                ( );iscase:
              return DOLLAR_BYTEprocessBulkReply
                ( );iscase:
              return ASTERISK_BYTEprocessMultiBulkReply
                ( );iscase:
              return COLON_BYTEprocessInteger
                ( );iscase:
              processError MINUS_BYTE(
                );isreturnnull
                ; default:
              thrownew
                JedisConnectionException ( "Unknown reply: "+( char )); b}}
          }
        public
      class
      
      RedisInputStream extends FilterInputStream public byte {
        readByte ( )throwsJedisConnectionException ensureFill ( {
          );return[
          ++ buf]count;}private
        void
          
      	ensureFill ( )throwsJedisConnectionException if ( {
              ) trycount >= limit= {
                . {
                  limit read in();buf=0
                  count ; if(
                  == -limit 1 )thrownew {
                    JedisConnectionException ( "Unexpected end of stream.");}}
                  catch
                ( IOException )throw enew {
                  JedisConnectionException ( );e}}
                }
              }
        	
      
      

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/735304.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-04-27
下一篇2022-04-27

发表评论

登录后才能评论

评论列表(0条)

    保存