主观下线(Subjective Down,SDOWN)
- 触发条件:在Redis Sentinel源码中,当Sentinel对某个Redis实例进行定期PING检测时,如果在配置的
down-after-milliseconds
时间内,连续多次PING都没有得到响应,该Sentinel就会将这个实例标记为主观下线。相关源码在sentinel.c
的sentinelIsInstanceAlive
函数中:
// 判断实例是否存活
int sentinelIsInstanceAlive(sentinelRedisInstance *ri) {
mstime_t delay = mstime() - ri->last_ping_time;
// 超过配置的down-after-milliseconds时间无响应
if (delay > ri->down_after_period) {
// 标记为主观下线
if (ri->flags & SRI_S_DOWN == 0) {
sentinelEvent(LL_WARNING,"sdown",ri,"%@ %lld ms no-reply",
sentinelRedisInstanceGetName(ri),
(long long)delay);
ri->flags |= SRI_S_DOWN;
}
return 0;
}
return 1;
}
- 状态转换逻辑:实例从正常状态转变为SDOWN状态,此时只有检测到的这个Sentinel认为该实例下线,其他Sentinel可能还认为该实例是正常的。
客观下线(Objective Down,ODOWN)
- 触发条件:当一个Sentinel将某个实例标记为主观下线后,它会向其他Sentinel发送
SENTINEL is-master-down-by-addr
命令,询问其他Sentinel对该实例的状态判断。如果同意该实例下线的Sentinel数量达到配置的 quorum
值(即多数Sentinel都认为该实例下线),就会将该实例标记为客观下线。在sentinel.c
的sentinelSendIsMasterDownByAddr
函数中:
// 发送SENTINEL is-master-down-by-addr命令
void sentinelSendIsMasterDownByAddr(sentinelRedisInstance *ri,
sentinelRedisInstance *target, int myvote) {
char buf[256];
int len = snprintf(buf,sizeof(buf),
"SENTINEL is-master-down-by-addr %s %d %d",
sentinelRedisInstanceGetAddr(target),
sentinelRedisInstanceGetPort(target),
myvote);
// 发送命令给其他Sentinel
sentinelSend(ri,buf,len);
}
- 状态转换逻辑:从主观下线状态,在满足
quorum
条件后,转换为客观下线状态。此时,所有Sentinel都达成共识,认为该实例确实下线。
故障转移流程
- 触发条件:当一个主节点被标记为客观下线后,Sentinel集群开始进行故障转移。首先,Sentinel会从多个从节点中选举出一个新的主节点。选举的依据是从节点的优先级(配置的
slave-priority
)、复制偏移量(replication offset
)以及运行ID(runid
)等。在sentinel.c
的sentinelSelectSlave
函数中:
// 选择一个从节点作为新的主节点
sentinelRedisInstance *sentinelSelectSlave(sentinelRedisInstance *master) {
list *it, *slaves = listSearchKey(master->slaves, "slaves");
sentinelRedisInstance *best = NULL;
// 遍历从节点列表
for (it = listFirst(slaves); it != NULL; it = listNext(it)) {
sentinelRedisInstance *slave = listNodeValue(it);
// 根据优先级、偏移量等条件选择最佳从节点
if (best == NULL ||
slave->slave_priority < best->slave_priority ||
(slave->slave_priority == best->slave_priority &&
slave->repl_offset > best->repl_offset))
{
best = slave;
}
}
return best;
}
- 状态转换逻辑:新选举出的从节点会被提升为主节点,其他从节点会重新配置为新主节点的从节点。
- 数据一致性维护机制:
- 对于从节点,在故障转移过程中,新主节点选举出来后,从节点会与新主节点进行全量或部分复制,以保证数据的一致性。从节点通过发送
PSYNC
命令与主节点协商复制方式。
- 在Sentinel层面,通过定期的心跳检测(PING命令)以及对节点状态的持续监控,确保所有节点状态的一致性。当有新节点加入或现有节点状态变化时,Sentinel会及时更新相关信息并通知其他Sentinel,从而保证整个集群对节点状态认知的一致性。