【发布时间】:2020-10-26 21:53:51
【问题描述】:
我正在使用 Spring Session 将我们的会话外部化到 Redis (AWS ElastiCache)。 Lettuce 被用作 Redis 的客户端。
我的 AWS Redis 配置如下:
- Redis 集群已启用
- 两个分片(即两个主分片)
- 每个主节点一个从节点
我的生菜配置如下:
<!-- Lettuce Configuration -->
<bean class="org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory">
<constructor-arg ref="redisClusterConfiguration"/>
</bean>
<!-- Redis Cluster Configuration -->
<bean id="redisClusterConfiguration" class="org.springframework.data.redis.connection.RedisClusterConfiguration">
<constructor-arg>
<list>
<value><!-- AMAZON SINGLE ENDPOINT HERE --></value>
</list>
</constructor-arg>
</bean>
当我们触发主节点的故障转移时会出现此问题。我在测试故障转移期间记录了以下事件
myserver-0001-001
cache-cluster
Monday, July 6, 2020 at 8:25:32 PM UTC+3
Finished recovery for cache nodes 0001
myserver-0001-001
cache-cluster
Monday, July 6, 2020 at 8:20:38 PM UTC+3
Recovering cache nodes 0001
myserver
replication-group
Monday, July 6, 2020 at 8:19:14 PM UTC+3
Failover to replica node myserver-0001-002 completed
myserver
replication-group
Monday, July 6, 2020 at 8:17:59 PM UTC+3
Test Failover API called for node group 0001
AWS 客户支持声称,只要在触发 Failover to replica node myserver-0001-002 completed 事件时(即触发故障转移后的 1m 和 15s)使用的 Redis 客户端是 Redis Cluster 感知的) 它应该能够连接到它(即新提升的master)。我们的客户端似乎只有在 Finished recovery for cache nodes 0001 事件被触发后(即 7m 和 32s 之后)才会重新连接。同时我们得到如下错误
org.springframework.data.redis.RedisSystemException: Error in execution; nested exception is io.lettuce.core.RedisCommandExecutionException: CLUSTERDOWN The cluster is down
在进行故障转移时,可以从 redis-cli 中看到以下信息。
endpoint:6379> cluster nodes
ffe51ecc6a8c1f32ab3774eb8f159bd64392dc14 172.31.11.216:6379@1122 master - 0 1594114396000 9 connected 0-8191
f8ff7a20f4c493b63ba65f107f575631faa4eb1b 172.31.11.52:6379@1122 slave 4ab10ca0a6a932179432769fcba7fab0faba01f7 0 1594114396872 2 connected
c18fee0e47800d792676c7d14782d81d7d1684e8 172.31.10.64:6379@1122 master,fail - 1594114079948 1594114077000 8 connected
4ab10ca0a6a932179432769fcba7fab0faba01f7 172.31.10.84:6379@1122 myself,master - 0 1594114395000 2 connected 8192-16383
endpoint:6379> cluster nodes
ffe51ecc6a8c1f32ab3774eb8f159bd64392dc14 172.31.11.216:6379@1122 master - 0 1594114461262 9 connected 0-8191
f8ff7a20f4c493b63ba65f107f575631faa4eb1b 172.31.11.52:6379@1122 slave 4ab10ca0a6a932179432769fcba7fab0faba01f7 0 1594114460000 2 connected
6a7339ae4df3c78e31c9cc8fd8cec4803eed5fc1 172.31.10.64:6379@1122 master - 0 1594114460256 0 connected
c18fee0e47800d792676c7d14782d81d7d1684e8 172.31.10.64:6379@1122 master,fail - 1594114079948 1594114077000 8 connected
4ab10ca0a6a932179432769fcba7fab0faba01f7 172.31.10.84:6379@1122 myself,master - 0 1594114458000 2 connected 8192-16383
endpoint:6379> cluster nodes
ffe51ecc6a8c1f32ab3774eb8f159bd64392dc14 172.31.11.216:6379@1122 master - 0 1594114509000 9 connected 0-8191
f8ff7a20f4c493b63ba65f107f575631faa4eb1b 172.31.11.52:6379@1122 slave 4ab10ca0a6a932179432769fcba7fab0faba01f7 0 1594114510552 2 connected
6a7339ae4df3c78e31c9cc8fd8cec4803eed5fc1 172.31.10.64:6379@1122 slave ffe51ecc6a8c1f32ab3774eb8f159bd64392dc14 0 1594114510000 9 connected
c18fee0e47800d792676c7d14782d81d7d1684e8 172.31.10.64:6379@1122 master,fail - 1594114079948 1594114077000 8 connected
4ab10ca0a6a932179432769fcba7fab0faba01f7 172.31.10.84:6379@1122 myself,master - 0 1594114508000 2 connected 8192-16383
endpoint:6379> cluster nodes
ffe51ecc6a8c1f32ab3774eb8f159bd64392dc14 172.31.11.216:6379@1122 master - 0 1594114548000 9 connected 0-8191
f8ff7a20f4c493b63ba65f107f575631faa4eb1b 172.31.11.52:6379@1122 slave 4ab10ca0a6a932179432769fcba7fab0faba01f7 0 1594114548783 2 connected
6a7339ae4df3c78e31c9cc8fd8cec4803eed5fc1 172.31.10.64:6379@1122 slave ffe51ecc6a8c1f32ab3774eb8f159bd64392dc14 0 1594114547776 9 connected
4ab10ca0a6a932179432769fcba7fab0faba01f7 172.31.10.84:6379@1122 myself,master - 0 1594114547000 2 connected 8192-16383
据我了解,Spring Session 使用的 Lettuce 是 Redis Cluster 感知的,因此 XML 配置中使用了 RedisClusterConfiguration 类。检查 SO 上的文档和一些类似问题以及 Lettuce 的 GitHub 问题页面,并没有让我清楚 Lettuce 如何在 Redis 集群模式下工作,特别是 AWS 将 IP 隐藏在一个公共端点下的诡计。
难道我的配置不足以让Lettuce连接到新提升的master吗?我是否需要在 Lettuce 中启用不同的模式才能接收来自 Redis 的通知并切换到新的主节点(例如拓扑刷新)?
另外,Lettuce 如何处理来自 AWS 的单个端点?它是在解析 IP 然后使用它们吗?它们被缓存了吗?
如果我想从所有四个节点进行读取,我的配置是否足够?在 Redis 集群中(即甚至在 AWS 的上下文之外),当从属被提升为主控时,是客户端轮询以获取信息还是集群以某种方式将其推送给客户端?
您拥有的任何可以阐明上述内容以及在 Lettuce、Redis 和 AWS 环境中的不同模式的资源(甚至是 Lettuce 源文件)都非常受欢迎。
如你所见,我对此仍然有些困惑。
非常感谢您提供的任何帮助和信息。
更新
启用了调试,并使用断点来拦截 bean 创建和配置拓扑刷新。看来是通过ClusterClientOptions的构造函数启用ClusterTopologyRefreshTask:
protected ClusterClientOptions(Builder builder) {
super(builder);
this.validateClusterNodeMembership = builder.validateClusterNodeMembership;
this.maxRedirects = builder.maxRedirects;
ClusterTopologyRefreshOptions refreshOptions = builder.topologyRefreshOptions;
if (refreshOptions == null) {
refreshOptions = ClusterTopologyRefreshOptions.builder() //
.enablePeriodicRefresh(DEFAULT_REFRESH_CLUSTER_VIEW) // Breakpoint here and enter to enable refreshing
.refreshPeriod(DEFAULT_REFRESH_PERIOD_DURATION) // Breakpoint here and enter to set the refresh interval
.closeStaleConnections(builder.closeStaleConnections) //
.build();
}
this.topologyRefreshOptions = refreshOptions;
}
看起来刷新OK了,但是现在的问题是,当Lettuce通过Spring Session使用而不是作为Redis的普通客户端时如何配置这个?
【问题讨论】:
-
我也遇到过这种情况,很好奇如何解决。 ??????
标签: amazon-web-services redis-cluster lettuce