分布式系统如zookeeper,redis的哨兵集群,为了达成共识都有选举的过程,如Sentinel系统内部通过投票来进行主节点的故障检测以及新主节点的选举。我们之前讲过zookeeper选举的过程,这次我们以Redis Sentinel为例。
Redis Sentinel 使用了一种定制化的算法来进行主节点(master)的故障转移(failover)过程。当主节点被认为下线后,Sentinel集群中的各个Sentinel节点会试图通过协商和投票来决定哪个从节点(slave)应该晋升为新的主节点。
具体来说,Sentinel集群中的每个在线Sentinel都可以尝试发起一次故障转移操作,通过向其他Sentinel发送消息并收集足够的投票(通常是大多数Sentinel节点的认可),来确定一个Sentinel作为领导者(Leader Sentinel)。领导者Sentinel负责执行故障转移的具体操作,包括选择最佳从节点升级为主节点,并通知其他Sentinel和客户端关于新的主节点信息。而判断主节点是否下线或进行主节点故障转移时,需要至少得到大多数Sentinel节点的同意。
这个大多数Sentinel节点,如何确认呢? num=(总节点数 / 2) + 1;
每个节点将自己收到的投票数和num比较,如果投票数 >= num,则成为leader。这个选举规则决定了我们部署节点的个数。
Redis Sentinel集群推荐部署奇数个节点,原因是为了在进行投票决策时能够更加明确地确定多数派,以防止出现投票平局。对于奇数个节点的集群,(总节点数 / 2) + 1
,可以很容易地界定出大于半数的节点集合,避免因网络分区或其他问题导致的决策延迟或不确定性。例如,如果是3个节点的集群,只要有2个节点同意就可以做出决策;如果是4个节点,理论上也是需要3个节点同意,但由于4是偶数,若恰好网络分割成两个相等大小的子集,每个子集都有2个节点,就可能导致无法达成共识,形成脑裂。因此,为了保证在大多数场景下能够高效且无歧义地达成决策,建议Sentinel集群部署奇数个节点。
所以,单纯的从理论上讲,部署节点的个数可以是奇数个,也可以是偶数个(部署偶数个也能运行)。当部署奇数个时,更容易界定出大于半数的节点集群个数。部署偶数个节点,会增大出现平票的概率。虽然在出现平票时,可以通过等待节点达到随机超时时间、增加优先级等额外的机制来重新发起选举,但从概率和对资源使用的情况来说,更推荐部署奇数个。
综上,遇到这种问题时,我们要从原理出发,去思考引起问题的根本所在,才能从根本上解决问题。