注意
本文档适用于 Ceph 开发版本。
Monitor Elections
原始算法
历史上,监控领导者选举非常简单:最低排名的监控器获胜!
这是通过一个低状态的“选举人”模块实现的(尽管现在它已被拆分为一个处理消息传递的选举人和一个做出投票选择的选举逻辑)。它跟踪选举周期,除此之外不多。奇数周期是选举;偶数周期有一个领导者,并让监控器做它正在进行的工作。当超时发生或监控器请求新的选举时,我们增加周期并向所有已知的监控器发送提议消息。
在正常情况下,这解决了问题,因为所有监控器都同意优先投票顺序,并且周期只有在监控器不参与或看到与已知提议者可能的冲突时才会增加。
问题
原始算法在各种网络分裂条件下根本不起作用。这在实践中并不经常出现,但随着社区和商业供应商将 Ceph 移动到需要使用“扩展集群”的空间中,这变得很重要。
新算法
我们仍然默认使用原始(“经典”)选举算法,但支持通过 CLI 允许用户更改为新的算法。这些算法作为不同的函数和选举逻辑类中的 switch 语句实现。
第一个算法非常简单:“禁止”允许你将监控器添加到禁止领导者列表。
算法:禁止
如果监控器在禁止列表中,它总是顺从另一个监控器,无论排名如何。否则,它与经典算法相同。
这个算法实际上只是作为一个演示和通往更高级的连接模式的基础,但在非对称网络和集群中可能有用。
算法:连接性
这个算法将每个连接的分数(双向,将在下一节讨论)作为输入,并试图选举得分最高的监控器。我们保持与经典算法相同的基本消息传递流程,其中选举是由对提议消息的反应驱动的。但这有几个挑战,因为与排名不同,分数不是静态的(并且在选举期间可能会改变!)为了确保选举周期不会产生多个领导者,我们必须维护两个关键不变量:
我们非常明确地处理这些:通过在开始选举(或增加周期)时分支我们的 peer_tracker 分数对象 stable_peer_tracker 的副本,并且如果我们当前的领导者选择不会顺从监控器,则拒绝顺从它。(所有提议消息都包括领导者正在使用的分数副本,因此对等方可以评估它们。)
当然,这些修改很容易阻塞。为了确保向前进展,我们做了进一步的调整:
这保证了只要网络相对稳定(即使断开连接):只要所有分数“视图”都导致相同的顺从顺序,选举将正常完成。并且通过在整个监控器集中广泛共享分数,监控器迅速收敛到最新的全局状态。
与经典和禁止处理程序相比,这个算法有一个进一步的重要特性:它可以忽略多数派外的对等方。通常,每当监控器 B 从多数派外的对等方 C 接收提议时,B 会自己触发新的选举,以给 C 加入的机会。但由于最高得分的监控器 A 可能与 C 网络分裂,这并不理想。因此,在连接性选举算法中,B 仅当 B 的分数表明集群会选择 A 以外的领导者时才“转发”提议消息。
连接评分
我们在 ConnectionTracker 类中实现评分,该类由 Elector 驱动,并作为资源提供给选举逻辑。Elector 负责发送 MMonPing 消息,并将结果报告到 ConnectionTracker 中,作为对 report_[live|dead]_connection 的调用,并提供相关的对等方和调用计数的时单位。(这些时单位是监控器中的秒,但 ConnectionTracker 是无知的,我们的单元测试计算简单的时间步长。)
我们配置了一个“半衰期”,每个报告都会更新对等方的当前状态(存活或死亡)及其总分。新分数是 current_score * (1 - units_alive / (2 * half_life)) + (units_alive / (2 * half_life))。(对于死亡报告,我们当然减去新增量,而不是加上它。)
我们可以进一步编码和解码 ConnectionTracker 以进行线传输,并接收包含所有已知分数的完整 ConnectionTracker 或表示单个对等方分数的 ConnectionReport,以从对等方中吸收分数。当然,这些分数都是版本化的,因此我们不会意外地倒退。
默认情况下,我们认为 2 秒后(mon_elector_ping_timeout)的 ping 失败,并且每秒 ping 活连接(mon_elector_ping_divisor)。半衰期是 12 小时(mon_con_tracker_score_halflife)。
由 Ceph 基金会带给您
Ceph 文档是一个社区资源,由非盈利的 Ceph 基金会资助和托管Ceph Foundation. 如果您想支持这一点和我们的其他工作,请考虑加入现在加入.