【エラー解決方法】Redis接続時にエラー発生!? を解決する方法(クラスタ構成編)

こんにちは、堀部です。
 
Spring Session + Redis(AWS ElastiCache)でセッション管理を行う方法 の過程で発生したエラーの解決方法です。
 
今回はクラスタ構成で冗長化されている環境で、Redisへの接続を行った時のエラーです。ノードを指定して接続を行っていましたが、どうもうまく接続ができませんでした。

エラー内容

org.springframework.data.redis.RedisConnectionFailureException: No reachable node in cluster; nested exception is redis.clients.jedis.exceptions.JedisNoReachableClusterNodeException: No reachable node in cluster
        at org.springframework.data.redis.connection.jedis.JedisExceptionConverter.convert(JedisExceptionConverter.java:67) ~[spring-data-redis-1.8.13.RELEASE.jar:na]
        at org.springframework.data.redis.connection.jedis.JedisExceptionConverter.convert(JedisExceptionConverter.java:41) ~[spring-data-redis-1.8.13.RELEASE.jar:na]
        at org.springframework.data.redis.PassThroughExceptionTranslationStrategy.translate(PassThroughExceptionTranslationStrategy.java:37) ~[spring-data-redis-1.8.13.RELEASE.jar:na]
        at org.springframework.data.redis.FallbackExceptionTranslationStrategy.translate(FallbackExceptionTranslationStrategy.java:37) ~[spring-data-redis-1.8.13.RELEASE.jar:na]
        at org.springframework.data.redis.connection.jedis.JedisClusterConnection.convertJedisAccessException(JedisClusterConnection.java:3985) ~[spring-data-redis-1.8.13.RELEASE.jar:na]
        at org.springframework.data.redis.connection.jedis.JedisClusterConnection.sMembers(JedisClusterConnection.java:1512) ~[spring-data-redis-1.8.13.RELEASE.jar:na]
        at org.springframework.data.redis.core.DefaultSetOperations$7.doInRedis(DefaultSetOperations.java:129) ~[spring-data-redis-1.8.13.RELEASE.jar:na]
        at org.springframework.data.redis.core.DefaultSetOperations$7.doInRedis(DefaultSetOperations.java:126) ~[spring-data-redis-1.8.13.RELEASE.jar:na]
        at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:207) ~[spring-data-redis-1.8.13.RELEASE.jar:na]
        at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:169) ~[spring-data-redis-1.8.13.RELEASE.jar:na]
        at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:91) ~[spring-data-redis-1.8.13.RELEASE.jar:na]
        at org.springframework.data.redis.core.DefaultSetOperations.members(DefaultSetOperations.java:126) ~[spring-data-redis-1.8.13.RELEASE.jar:na]
        at org.springframework.data.redis.core.DefaultBoundSetOperations.members(DefaultBoundSetOperations.java:91) ~[spring-data-redis-1.8.13.RELEASE.jar:na]
        at org.springframework.session.data.redis.RedisSessionExpirationPolicy.cleanExpiredSessions(RedisSessionExpirationPolicy.java:131) ~[spring-session-1.3.2.RELEASE.jar:na]
        at org.springframework.session.data.redis.RedisOperationsSessionRepository.cleanupExpiredSessions(RedisOperationsSessionRepository.java:398) ~[spring-session-1.3.2.RELEASE.jar:na]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_171]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_171]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_171]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_171]
        at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65) ~[spring-context-4.2.1.RELEASE.jar:4.2.1.RELEASE]
        at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-4.2.1.RELEASE.jar:4.2.1.RELEASE]
        at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81) [spring-context-4.2.1.RELEASE.jar:4.2.1.RELEASE]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_171]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_171]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_171]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [na:1.8.0_171]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_171]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_171]
        at java.lang.Thread.run(Thread.java:748) [na:1.8.0_171]
Caused by: redis.clients.jedis.exceptions.JedisNoReachableClusterNodeException: No reachable node in cluster
        at redis.clients.jedis.JedisSlotBasedConnectionHandler.getConnection(JedisSlotBasedConnectionHandler.java:57) ~[jedis-2.9.0.jar:na]
        at redis.clients.jedis.JedisSlotBasedConnectionHandler.getConnectionFromSlot(JedisSlotBasedConnectionHandler.java:74) ~[jedis-2.9.0.jar:na]
        at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:116) ~[jedis-2.9.0.jar:na]
        at redis.clients.jedis.JedisClusterCommand.runBinary(JedisClusterCommand.java:60) ~[jedis-2.9.0.jar:na]
        at redis.clients.jedis.BinaryJedisCluster.smembers(BinaryJedisCluster.java:588) ~[jedis-2.9.0.jar:na]
        at org.springframework.data.redis.connection.jedis.JedisClusterConnection.sMembers(JedisClusterConnection.java:1510) ~[spring-data-redis-1.8.13.RELEASE.jar:na]
        ... 23 common frames omitted
ERROR TaskUtils$LoggingErrorHandler - Unexpected error occurred in scheduled task.
org.springframework.data.redis.RedisConnectionFailureException: No reachable node in cluster; nested exception is redis.clients.jedis.exceptions.JedisNoReachableClusterNodeException: No reachable node in cluster
        at org.springframework.data.redis.connection.jedis.JedisExceptionConverter.convert(JedisExceptionConverter.java:67) ~[spring-data-redis-1.8.13.RELEASE.jar:na]
        at org.springframework.data.redis.connection.jedis.JedisExceptionConverter.convert(JedisExceptionConverter.java:41) ~[spring-data-redis-1.8.13.RELEASE.jar:na]
        at org.springframework.data.redis.PassThroughExceptionTranslationStrategy.translate(PassThroughExceptionTranslationStrategy.java:37) ~[spring-data-redis-1.8.13.RELEASE.jar:na]
        at org.springframework.data.redis.FallbackExceptionTranslationStrategy.translate(FallbackExceptionTranslationStrategy.java:37) ~[spring-data-redis-1.8.13.RELEASE.jar:na]
        at org.springframework.data.redis.connection.jedis.JedisClusterConnection.convertJedisAccessException(JedisClusterConnection.java:3985) ~[spring-data-redis-1.8.13.RELEASE.jar:na]
        at org.springframework.data.redis.connection.jedis.JedisClusterConnection.sMembers(JedisClusterConnection.java:1512) ~[spring-data-redis-1.8.13.RELEASE.jar:na]
        at org.springframework.data.redis.core.DefaultSetOperations$7.doInRedis(DefaultSetOperations.java:129) ~[spring-data-redis-1.8.13.RELEASE.jar:na]
        at org.springframework.data.redis.core.DefaultSetOperations$7.doInRedis(DefaultSetOperations.java:126) ~[spring-data-redis-1.8.13.RELEASE.jar:na]
        at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:207) ~[spring-data-redis-1.8.13.RELEASE.jar:na]
        at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:169) ~[spring-data-redis-1.8.13.RELEASE.jar:na]
        at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:91) ~[spring-data-redis-1.8.13.RELEASE.jar:na]
        at org.springframework.data.redis.core.DefaultSetOperations.members(DefaultSetOperations.java:126) ~[spring-data-redis-1.8.13.RELEASE.jar:na]
        at org.springframework.data.redis.core.DefaultBoundSetOperations.members(DefaultBoundSetOperations.java:91) ~[spring-data-redis-1.8.13.RELEASE.jar:na]
        at org.springframework.session.data.redis.RedisSessionExpirationPolicy.cleanExpiredSessions(RedisSessionExpirationPolicy.java:131) ~[spring-session-1.3.2.RELEASE.jar:na]
        at org.springframework.session.data.redis.RedisOperationsSessionRepository.cleanupExpiredSessions(RedisOperationsSessionRepository.java:398) ~[spring-session-1.3.2.RELEASE.jar:na]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_171]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_171]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_171]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_171]
        at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65) ~[spring-context-4.2.1.RELEASE.jar:4.2.1.RELEASE]
        at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-4.2.1.RELEASE.jar:4.2.1.RELEASE]
        at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81) [spring-context-4.2.1.RELEASE.jar:4.2.1.RELEASE]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_171]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_171]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_171]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [na:1.8.0_171]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_171]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_171]
        at java.lang.Thread.run(Thread.java:748) [na:1.8.0_171]
Caused by: redis.clients.jedis.exceptions.JedisNoReachableClusterNodeException: No reachable node in cluster
        at redis.clients.jedis.JedisSlotBasedConnectionHandler.getConnection(JedisSlotBasedConnectionHandler.java:57) ~[jedis-2.9.0.jar:na]
        at redis.clients.jedis.JedisSlotBasedConnectionHandler.getConnectionFromSlot(JedisSlotBasedConnectionHandler.java:74) ~[jedis-2.9.0.jar:na]
        at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:116) ~[jedis-2.9.0.jar:na]
        at redis.clients.jedis.JedisClusterCommand.runBinary(JedisClusterCommand.java:60) ~[jedis-2.9.0.jar:na]
        at redis.clients.jedis.BinaryJedisCluster.smembers(BinaryJedisCluster.java:588) ~[jedis-2.9.0.jar:na]
        at org.springframework.data.redis.connection.jedis.JedisClusterConnection.sMembers(JedisClusterConnection.java:1510) ~[spring-data-redis-1.8.13.RELEASE.jar:na]
        ... 23 common frames omitted

エラー発生時のバージョン

エラー発生時のバージョンは以下になります。
 

Java
1.8
Spring Framework
4.2.1
jedis
2.9.0
Redis
3.2.6

エラー解決方法

いろいろと調べた結果、SpringSession / Jedis はクラスターモードかつSSL有効化には対応していないようで、RedisClusterではSSLで接続できないことがわかりました。
 
今後、SSL接続ができるようになるかもしれませんが、少なくとも私がRedisを使った開発を行っていた2018年8月頃はSSL接続はサポートされていませんでした。非SSLだと接続できるため、対応としてはSSLでの接続をやめました。
 
そのほかの接続方法にRedisSentinelを使った方法があるようですが、こちらは検証していないのでもしかしたらできるかもしれません。
 

	<!-- Redis接続情報 -->
	<bean id="redisClusterConfiguration" class="org.springframework.data.redis.connection.RedisClusterConfiguration">
		<property name="clusterNodes">
			<set>
				<bean class="org.springframework.data.redis.connection.RedisNode">
					<constructor-arg name="host" value="ノード1のホスト名" />
					<constructor-arg name="port" value="6379" type="int" />
				</bean>
				<bean class="org.springframework.data.redis.connection.RedisNode">
					<constructor-arg name="host" value="ノード2のホスト名" />
					<constructor-arg name="port" value="6379" type="int" />
				</bean>
			</set>
		</property>

		<property name="maxRedirects" value="5" />
	</bean>
	<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" 
			p:host-name="localhost" p:port="6379" p:useSsl="false">
		<constructor-arg ref="redisClusterConfiguration" />
  </bean>

 
これで無事、接続ができました。
 
 
 
 
《関連記事》

記事をシェア
MOST VIEWED ARTICLES