我需要定期执行某些工作(比如每分钟)。如果单个节点执行此操作,则会出现单点故障。为了避免这种情况,我想到了以下方案:
1. Nodes form a raft cluster, with leader election
2. Only the leader executes scheduled jobs
2.1. Every node checks if it is the leader before executing jobs.
3. Replication of commands is not required, thus we would not have a replicated log
为了实现这一点,只有领导人选举是必要的。那么我有可能只实现RAFT的领导者选举部分并实现这一目标吗?这种方法有问题吗?
更新1 以下是错误的假设:(这不可能发生)
<德尔> *我可以看到的一个问题是:在网络分区的情况下两个领导者的可能性。但我认为我可以忽略这一点。* 德尔>更新2: 不需要重新启动失败的作业
注意:我可能会使用Zookeeper或类似的东西来实现这一目标,但我的目标是编写自己的
答案 0 :(得分:1)
领导者选举需要一个日志[领导者做的第一件事是写一个新的日志条目]和其他一些簿记持久状态,所以即使你没有复制任何命令,你也需要一个日志。你不需要一个非常高效的日志或传输,但我认为你将会写出筏纸上描述的大部分内容。
我建议寻找一个库或使用ZooKeeper或etcd等现有服务进行协调,如果你的系统可以同时处理正在运行的作业[就像你指出的分区一样]你可以忽略],那么你可以节省很多工作,并且总是在很多主机上运行它。
答案 1 :(得分:1)
不,不需要日志。领导者 - 跟随者候选状态机和超时足以让主人知道其领导者。 (在这里试试https://raft.github.io/!)
但是,请注意,领导者没有意识到由于网络分区而失去领导力的时间很短。
有两种方法可以解决这个问题。
<强> A 即可。领导者只能在心跳的法定人数最后一次确认后才能在安全窗口内行动。 这有问题,如更新中所示。
回想一下,有一个名为 election_timeout 的参数和另一个我称之为 hearbeat_timeout 的未命名参数。在 election_timeout 过去之后领导者永远不应该工作,因为它已经收到了它的最后一次更新法定时间,以便数据包通过网络传输。
|<- hearbeat_timeout ->|
|<---------------- election_timeout ------------------>|
|<- safety_margin ->|
|<----- safe_time_to_do_work ----->|
<强>乙即可。当一位领导人新当选时,应该等待一段时间才能担任领导。
|<----------------- election_timeout ----------------->|
|<- hearbeat_timeout ->|
|<---- safety_margin ---->|
|<-- safe_time_to_do_work -->|
你会想要在给定的时间记录谁是领导者;在应用程序日志中或在木筏本身。
如果你做最终使用筏日志,请确保每个领导者提交某些东西,即使它只是一个字符串“主机XYZ现在是领导者”,因为筏有时需要log to move forward提交以前的值。
更新:所有这些都有一些重要的微妙之处。有一种情况是,过时的主持人可以很容易地废除领导者。
考虑主机没有收到一些心跳的情况。选举计时器耗尽,它将自己广播为新一代的候选人。 这可能随时发生,并使 A 的安全边缘无效。筏中没有任何东西可以阻止这种情况,我一直认为这是木筏的一个缺点
如果您想保留方案 A ,您可以修改协议,以便关注者拒绝其心跳内的选举请求。你还必须确保领导者在某个时候放弃控制权。这将显着减慢故障转移。