Tendis icon indicating copy to clipboard operation
Tendis copied to clipboard

如果一个槽位的主从都挂了,那么整个集群将不可读写,包括其他槽位

Open yuandongjian opened this issue 3 years ago • 6 comments

三主三从,槽位分成三份,先kill其中一个slave,再kill掉对应master 此时整个集群被标记为down,无论客户端访问的key在哪个槽位,都会提示(error) CLUSTERDOWN The cluster is down 这种状态不可恢复,除非人工介入。

另外,如果master挂了,看代码slave是以上次同步时间来决定是否有数据落后,进而决定是否可以晋升为主。一旦master退出缓慢(比如:刷盘阻塞),data_age将会比较大,导致slave无法晋升为主,最可怕的是集群会被标记为down,客户端表现仍然为(error) CLUSTERDOWN The cluster is down,整个集群灾难级别的不可用。

  uint64_t syncTime = replMgr->getLastSyncTime();
  data_age = msSinceEpoch() - syncTime;
  //... 
  mstime_t limitTime =
    ((mstime_t)gBinlogHeartbeatSecs * 1000) + nodeTimeout * slavefactor;
  if (slavefactor && data_age > limitTime) {
     //...
      LOG(ERROR) << "vote fail, data age to large:" << data_age
                 << " limtTime is:" << limitTime;
      return {ErrorCodes::ERR_CLUSTER, "data age to big"};
  } 

希望可以指正我的错误,以及使用上如何避免出现整个集群不可用且无法恢复的问题

yuandongjian avatar May 21 '21 02:05 yuandongjian

的确也遇到这种情况了

jackerzhou avatar May 21 '21 07:05 jackerzhou

问题1:如果一个槽位的主备都故障了,希望其他节点继续提供服务,可以将cluster-require-full-coverage配置为NO 详细可查看 https://redis.io/topics/cluster-tutorial

这个参数给redis保持一致,默认为yes

需要注意的是,如果这个配置设置为NO,有可能出现网络分区导致的异常,上述文章也有描述这个参数的作用。

问题2:如果主备都故障,或者slave由于数据落后太久导致无法提主,可以通过将参数cluster-slave-validity-factor变大, 这个参数的目的就是为了处理这种情况。 这个参数的语义是,假设slave数据落后N秒,如果 N < cluster-node-timeout * cluster-slave-validity-factor,则该slave可以提主,否则无法提主

TendisDev avatar May 24 '21 13:05 TendisDev

@TendisDev 感谢您细致的答疑。

关于cluster-node-timeout,Redis Cluster好像有个这样的注意点:

一些阻塞命令(flushall, del key1 key2 …)会造成redis在‘cluster-node-timeout’时间内无法响应其他节点的ping请求, 从而导致其他节点都把该redis标记出了pfail状态,进而产生failover

Tendis是多线程的,应该不存在这个问题吧?

另外,我还有一些问题,我发现Tendis在kill时会丢失一部分写入成功的数据,以下是我的测试步骤:

  1. 三主三从集群,version:2.3.1-rocksdb-v5.13.4
  2. 持续写入新数据,并记录下写入成功的数据
  3. kill 其中一个master。此时Tendis自动failover,部分写请求失败
  4. 使用step 2写入成功的key来获取数据,发现部分数据读取的结果为null
  5. 启动被杀掉的老master,并手动failover使其重新成为主,再次获取step 4获取失败的key,仍然为null
  6. 以上步骤应该可以证明,在自动failover期间,Tendis丢失了一部分返回给客户端OK的数据

我们可以接受kill -9丢失一部分数据,但是kill时数据丢失是否可以规避?

yuandongjian avatar May 26 '21 09:05 yuandongjian

你好,如果希望所有数据强制落地,可以使用这个参数,保证master所有操作都会持久化,但延时会增大。 image

但是,当前版本的tendis使用的是异步复制,failover过程中,并不能保证slave一定已经同步完成,所以slave自动提主之后可能存在数据落后。 基于raft的主备强一致版本内部正在开发中。

TendisDev avatar May 27 '21 03:05 TendisDev

关于cluster-node-timeout,Redis Cluster好像有个这样的注意点:

一些阻塞命令(flushall, del key1 key2 …)会造成redis在‘cluster-node-timeout’时间内无法响应其他节点的ping请求, 从而导致其他节点都把该redis标记出了pfail状态,进而产生failover

Tendis是多线程的,应该不存在这个问题吧?

是的,tendis不会存在这个问题

TendisDev avatar May 27 '21 03:05 TendisDev

@TendisDev kill -15的时候是有时间来做出数据同步的,是否能针对kill -15来做一版简单的优化

yuandongjian avatar May 28 '21 01:05 yuandongjian