4

我对实现 RAFT 有以下疑问:

考虑以下场景\实现:

  1. RAFT 领导者收到一个命令条目,它将条目附加到内存数组中,然后将条目发送给跟随者(带有心跳)
  2. 追随者接收条目并将其附加到他们的内存数组中,然后发送响应它已收到条目
  3. 然后领导者通过将条目写入持久存储(文件)来提交条目领导者在心跳中发送最新的提交索引
  4. 追随者然后通过将条目存储到他们的持久存储(文件)来根据领导者的提交索引提交条目

RAFT 的实现之一(链接:https ://github.com/peterbourgon/raft/ )似乎以这种方式实现它。我想确认这是否正常。

如果条目由领导者和追随者“在内存中”维护,直到它被提交,是否可以?在什么情况下这种情况可能会失败?

4

3 回答 3

4

我不同意接受的答案。

  1. 磁盘并不神秘耐用。假设磁盘是服务器本地的,它可能会永久失败。所以很明显,写入磁盘并不能让你摆脱这种情况。复制持久性的,前提是副本存在于不同的故障域中,如果您认真对待持久性,它们将会是。当然,磁盘不会遭受的进程有很多危害(linux oom 被杀死,一般的 oom,电源等),但是专用机器上的专用进程可以做得很好。特别是如果日志存储是 ramfs,那么进程重启不是问题。

  2. 如果日志存储丢失,那么主机身份也应该丢失。A、B、C 识别日志。新日志,新标识。B 在(潜在的)存储丢失后“重新加入”只是一个错误的实现。新进程不能声称 B 的身份,因为它不能确定它拥有 B 拥有的所有信息。就像总是刷新到磁盘的情况一样,如果我们更换托管 B 的机器的磁盘,我们不能只是重新启动进程并将其配置为具有 B 的身份。那将是无稽之谈。在这两种情况下,它都应该以 D 身份重新启动,然后要求加入集群。到那时,丢失已提交写入的问题就烟消云散了。

于 2018-11-07T10:50:28.137 回答
3

我通过发布到 raft-dev google group 找到了问题的答案。我已经添加了答案以供参考。

请参考:https ://groups.google.com/forum/#!msg/raft-dev/_lav2NeiypQ/1QbUB52fkggJ

引用迭戈的回答:

为了安全,即使面对相关的停电,大多数服务器都需要在其影响被外部化之前持久化日志条目。任何少于多数的服务器都可能永久失效,从而导致数据丢失/损坏

引用Ben Johnson对我的电子邮件的回答:

不,服务器必须在被视为仲裁的一部分之前将条目刷新到磁盘。

例如,假设您有一个名为 A、B 和 C 的节点集群,其中 A 是领导者。

  1. 节点 A 将条目复制到节点 B。

  2. 节点 B 将条目存储在内存中并响应节点 A。

  3. 节点 A 现在有一个仲裁并提交条目。

  4. 然后节点 A 与节点 B 和 C 分开。

  5. 然后节点 B 死亡并丢失该条目的内存副本。

  6. 节点 B 重新启动。

  7. 当节点 B & C 然后去选举领导者时,“提交”条目将不会出现在他们的日志中。

  8. 当节点 A 重新加入集群时,它会出现不一致的日志。该条目将已提交并应用于状态机,因此无法回滚。

于 2014-04-29T17:45:27.137 回答
0

我认为条目在提交之前应该是持久的。

我们以 Raft 扩展论文的图 8(e) 为例。如果提交时条目是持久的,则:

  1. S1 将 4 复制到 S2 和 S3,然后提交 2 和 4。
  2. 所有服务器崩溃。因为 S2 和 S3 不知道 S1 已提交 2 和 4,所以他们不会提交 2 和 4。因此 S1 已提交 1、2、4,S2、S3、S4、S5 已提交 1。
  3. 除 S1 外,所有服务器都重新启动。
  4. 因为只有提交的条目是持久的,所以 S2、S3、S4、S5 具有相同的单个条目:1。
  5. S2 被选为领导者。
  6. S2 将新条目复制到除崩溃的 S1 之外的所有其他服务器。
  7. S1 重新启动。因为 S2 的条目比 S1 更新,所以 S1 的 2 和 4 被之前的新条目替换。

结果,已提交的条目 2 和 4 丢失。所以我认为未提交的条目也应该是持久的。

于 2019-05-26T14:50:27.683 回答