我需要一些帮助,我们的服务使用莴苣5.1.6版本,总共部署了22个docker节点。
每当部署服务时,多个docker节点都会出现错误:readonly您不能针对只读从属服务器进行写入。
重新启动有问题的docker节点错误不再出现
redis服务器配置:
8主8从
停止写入bgsave错误否
从服务器过时数据是
从属只读是
群集已启用是
集群配置文件“/data/server/redis cluster/{port}/conf/node.conf”
莴苣配置:
ClientResources res = DefaultClientResources.builder()
.commandLatencyPublisherOptions(
DefaultEventPublisherOptions.builder()
.eventEmitInterval(Duration.ofSeconds(5))
.build()
)
.build();
redisClusterClient = RedisClusterClient.create(res, REDIS_CLUSTER_URI);
redisClusterClient.setOptions(
ClusterClientOptions.builder()
.maxRedirects(99)
.socketOptions(SocketOptions.builder().keepAlive(true).build())
.topologyRefreshOptions(
ClusterTopologyRefreshOptions.builder()
.enableAllAdaptiveRefreshTriggers()
.build())
.build());
RedisAdvancedClusterCommands<String, String> command = redisClusterClient.connect().sync();
command.setex("some key", 18000, "some value");
出现的异常:
io.lettuce.core.RedisCommandExecutionException: READONLY You can't write against a read only slave.
at io.lettuce.core.ExceptionFactory.createExecutionException(ExceptionFactory.java:135)
at io.lettuce.core.LettuceFutures.awaitOrCancel(LettuceFutures.java:122)
at io.lettuce.core.cluster.ClusterFutureSyncInvocationHandler.handleInvocation(ClusterFutureSyncInvocationHandler.java:123)
at io.lettuce.core.internal.AbstractInvocationHandler.invoke(AbstractInvocationHandler.java:80)
at com.sun.proxy.$Proxy135.setex(Unknown Source)
at com.xueqiu.infra.redis4.RedisClusterImpl.lambda$setex$164(RedisClusterImpl.java:1489)
at com.xueqiu.infra.redis4.RedisClusterImpl$$Lambda$1422/1017847781.apply(Unknown Source)
at com.xueqiu.infra.redis4.RedisClusterImpl.execute(RedisClusterImpl.java:526)
at com.xueqiu.infra.redis4.RedisClusterImpl.executeTotal(RedisClusterImpl.java:491)
at com.xueqiu.infra.redis4.RedisClusterImpl.setex(RedisClusterImpl.java:1489)
1条答案
按热度按时间jv2fixgn1#
面对分布式中间件,客户端会在客户端放置一些分区、分片等关系进行管理。
redis cluster的slotMap管理:
所采用的方法是使用一个slotcache数组,以数组的形式在本地缓存每个slot对应的节点。
当有密钥需要读写到服务器时,通过客户端的crc16计算出时隙,然后在缓存中获取节点。
redis集群服务器进行集群管理时,在每个节点的local node.conf中记录slot与节点的Map关系。
当乒乓球数据通过gossip协议交换时,这些元数据信息被广播以形成最终一致的元数据信息。
但是,如果服务器端的插槽Map关系中存在错误,客户端将使用这些错误的数据。
这次问题出现在这里。服务器部分节点将插槽Map到从属节点,这样客户端缓存的插槽Map到从属节点,读写请求被发送到从属节点,从而导致错误。