在 raft 的论文文档第 6.4 章中,它给出了绕过 Raft 日志进行只读查询并仍然保持线性化的步骤:
- 如果领导者尚未将其当前任期内的条目标记为已提交,则它会一直等到这样做。领导者完整性属性保证领导者拥有所有已提交的条目,但在其任期开始时,它可能不知道那些是哪些。要找出答案,它需要从其任期内提交一个条目。Raft 通过让每个领导者在其任期开始时将一个空白的 no-op 条目提交到日志中来处理这个问题。一旦这个无操作条目被提交,领导者的提交索引在其任期内将至少与任何其他服务器一样大。
- 领导者将其当前提交索引保存在局部变量 readIndex 中。这将用作查询操作所针对的状态版本的下限。
- 领导者需要确保它没有被它不知道的新领导者取代。它发出新一轮的心跳并等待大多数集群的确认。一旦收到这些确认,领导者就知道在发送心跳的那一刻,领导者不可能存在更长的任期。因此,当时 readIndex 是集群中任何服务器所见过的最大提交索引。
- 领导者等待其状态机至少前进到 readIndex;这足以满足线性化。
- 最后,领导者针对其状态机发出查询,并用结果回复客户端。
我的问题:
a)对于第1步,是否仅适用于刚刚选举出领导者时的情况?因为只有新领导者没有为当前任期提交条目。并且由于 no-op 条目对于找出当前提交的条目是必要的,那么实际上这一步在选举完成时总是需要的,但不仅限于只读查询吗?换句话说,通常,当领导者活动一段时间时,它必须在其任期内提交条目(包括无操作条目)。
b) 对于第 3 步,这是否意味着只要领导者需要提供只读查询,就会发送一个额外的心跳,而不管当前未完成的心跳(已发送但尚未收到主要响应)或下一个预定的心跳?
c) 对于第 4 步,是否仅适用于追随者(对于追随者帮助卸载只读查询处理的情况)?因为在领导者上,提交的索引已经意味着它被应用于本地状态机。
总而言之,正常情况下,leader(活跃一段时间)只需要做第3步和第5步,对吧?