Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
yuandongjian opened this issue May 21, 2021 · 6 comments

Comments

@yuandongjian
Copy link

yuandongjian commented May 21, 2021

三主三从,槽位分成三份,先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"};
  } 

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

@jackerzhou
Copy link

的确也遇到这种情况了

@TendisDev
Copy link
Collaborator

问题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可以提主,否则无法提主

@yuandongjian
Copy link
Author

yuandongjian commented May 26, 2021

@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时数据丢失是否可以规避?

@TendisDev
Copy link
Collaborator

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

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

@TendisDev
Copy link
Collaborator

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

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

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

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

@yuandongjian
Copy link
Author

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

TendisDev pushed a commit that referenced this issue Jun 4, 2021
[bug fixed]  fix cluster nodes coredump bugs and info levelstats for binlog #107 #110
### MR描述
1. #107 
2. #110 
3. add _seeked for BinlogCursor/AllDataCursor/BasicDataCursor,避免冗余的seek("")

### 修改动机和上下文背景
<!--- 为什么需要此修改, 解决了什么问题 -->
<!---如果解决了相关的#issue, 在此处进行关联(#issue, close #issue) -->

### 此MR如何进行测试 ?
<!--- 请描述测试MR的细节 -->
<!--- 包括测试的环境以及执行的测试用例 -->
<!--- 说明 change 如何影响其他部分的代码 etc. -->

### change 类型
<!---你的代码引入了何种类型的change, 在所有关联的复选框前选择"x" -->
- [ ] Bug fix (修复了issue的非侵入式修改)
- [ ] New feature (增加功能的非侵入式修改)
- [ ] Breaking change (修复或者增加特性, 但是会造成现有行为的非预期行为)

### 清单
<!--- 查看下述选项,并进行"x"勾选 -->
<!--- 如果你对所有都不确定, 请随时咨询我们 -->
- [ ] 遵循项目的Code-Style
- [ ] Change 需要文档的修改
- [ ] 我已经进行相关文档的修改
- [ ] 我的MR已经通过的相关流水线测试
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants