0

日志清理会删除对当前状态没有贡献的条目,那么如果慢速追随者或新成员需要它们,如何为这些删除的条目构造 AppendEntries?需要修改 AppendEntries 以便它可以包含不连续的条目?还是改用快照?

4

1 回答 1

2

Copycat使用一种类似于Raft 论文中描述的日志清理算法的算法来实现一种增量压缩形式。因此,有一些关于如何做到这一点的先例和代码。Copycat 的增量压缩算法与 Raft 文献中描述的算法不同,它在压缩后保留日志中条目的位置,以利用顺序读取而不是将条目复制到日志头部,但AppendEntries发送给跟随者的 RPC 仍然可以与批次条目中的空白一起发送。

AppendRequest我们只需将索引包含在批次中的每个条目中即可处理丢失的条目。但这也需要日志中的一些机制来跳过关注者的条目。如果追随者从领导者日志的压缩段接收条目,则追随者必须通过在写入日志时跳过条目来复制领导者日志的结构。

Raft 中的增量压缩还有一些其他挑战,这些挑战在 Raft 文献中没有广泛描述,特别是在处理墓碑方面。墓碑的问题之一是它们在应用到所有服务器之前无法从日志中删除。如果一个 tombstone 已提交并在复制到跟随者(可能已分区)之前从领导者的日志中删除,则该跟随者可能永远不会删除其状态。在 Copycat 中,这需要添加一个globalIndex来跟踪存储在所有服务器上的最高索引。

但我离题了,我意识到我过度回答了你的问题。Raft 中的增量压缩是一个有趣且具有挑战性的问题。如果您有兴趣阅读有关如何在 Copycat 中解决它的更多信息,我已经编写了有关 Copycat 增量压缩算法的大量文档,包括对处理墓碑的各种问题和在顶部实现快照的方法的深入描述增量压缩算法。

如果你从 Copycat 的文档中了解到一件事,很可能是 Raft 中的增量压缩有很多复杂性。我们花了好几个月的时间才算出其中的所有算法,但也许我们学到的经验教训对你有用。

可以肯定的是,在 Raft 中实现快照比在 Copycat 中的增量压缩算法要容易得多。但它仍然存在一些复杂性。例如,Java 不太适合 fork 进程以防止在快照期间阻塞,这也是我们选择为 Raft 编写增量压缩算法的原因之一。在 Copycat 中实现对大型快照的支持需要将完整的状态机状态复制到内存中,或者添加领导者传输机制以确保领导者在为大型状态机制作快照时不会被阻塞。权衡选项与您环境的实际情况。

于 2016-05-16T00:28:41.423 回答