Tendis
Tendis copied to clipboard
如果一个槽位的主从都挂了,那么整个集群将不可读写,包括其他槽位
三主三从,槽位分成三份,先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"};
}
希望可以指正我的错误,以及使用上如何避免出现整个集群不可用且无法恢复的问题
的确也遇到这种情况了
问题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 感谢您细致的答疑。
关于cluster-node-timeout
,Redis Cluster好像有个这样的注意点:
一些阻塞命令(flushall, del key1 key2 …)会造成redis在‘cluster-node-timeout’时间内无法响应其他节点的ping请求, 从而导致其他节点都把该redis标记出了pfail状态,进而产生failover
Tendis是多线程的,应该不存在这个问题吧?
另外,我还有一些问题,我发现Tendis在kill时会丢失一部分写入成功的数据,以下是我的测试步骤:
- 三主三从集群,version:2.3.1-rocksdb-v5.13.4
- 持续写入新数据,并记录下写入成功的数据
- kill 其中一个master。此时Tendis自动failover,部分写请求失败
- 使用step 2写入成功的key来获取数据,发现部分数据读取的结果为null
- 启动被杀掉的老master,并手动failover使其重新成为主,再次获取step 4获取失败的key,仍然为null
- 以上步骤应该可以证明,在自动failover期间,Tendis丢失了一部分返回给客户端OK的数据
我们可以接受kill -9丢失一部分数据,但是kill时数据丢失是否可以规避?
你好,如果希望所有数据强制落地,可以使用这个参数,保证master所有操作都会持久化,但延时会增大。
但是,当前版本的tendis使用的是异步复制,failover过程中,并不能保证slave一定已经同步完成,所以slave自动提主之后可能存在数据落后。 基于raft的主备强一致版本内部正在开发中。
关于cluster-node-timeout,Redis Cluster好像有个这样的注意点:
一些阻塞命令(flushall, del key1 key2 …)会造成redis在‘cluster-node-timeout’时间内无法响应其他节点的ping请求, 从而导致其他节点都把该redis标记出了pfail状态,进而产生failover
Tendis是多线程的,应该不存在这个问题吧?
是的,tendis不会存在这个问题
@TendisDev kill -15的时候是有时间来做出数据同步的,是否能针对kill -15来做一版简单的优化