Raft中用到的RPC

分布式一致性问题

Posted by bbkgl on October 20, 2019

韶华不为少年留

恨悠悠

几时休

在阅读Raft论文的时候发现其中用到了三种RPC,都是由领导人发出:

  • 心跳包RPC,用于维持领导人的权威
  • 发送请求投票的 RPC,拉票
  • 附加条目 RPC,用于其他服务器的日志复制

其实第一种和第三种是同一类型的RPC,只是在不同情况下作用不一样:当其entries域为空时,该RPC作为Leader的心跳;当entries域不为空时,请求其他节点将entries域中的log添加到自己的log中。

根据论文中的表达,使用的RPC如下:

  • RequestVote RPC,拉票RPC
  • AppendEntries RPC,日志复制和心跳包RPC

RequestVote RPC

顾名思义,就是用来拉票的RPC,先来看下论文中对该RPC的图片描述:

H73bd3d67996b4b9bbdbe92ae39ebb8c7o

候选人远程调用让其他人给自己征集选票,

  • 参数:

    • term:候选人的任期号
    • candidateId:候选人的ID,标识,比如主机号及端口号
    • lastLogIndex:候选人最后日志条目的索引值
    • lastLogTerm:候选人最后日志条目的任期号
  • 返回值:

    • term:当前任期号,以便于候选人更新自己的任期号
    • voteGranted:候选人赢得了此张选票时为真,即被调用对象是否投票给该候选人
  • 接受者要实现:

    • 如果候选人的任期小于当前任期,则返回false(不投票给你)
    • 如果 votedFor 为空或者为 candidateId,并且候选人的日志至少和自己一样新,那么就投票给他,也就是自己还没投给别人,且这个候选人合法的话,就投票给他

AppendEntries RPC

领导人给其他人复制日志的RPC,也用作任期时心跳,巩固地位。

Hcb5c483f2b3b4f3cbcccb70c0516a9a3P

  • 参数
    • term:调用RPC领导人的任期
    • leaderId:领导人的ID,便于群众重定向请求
    • prevLogIndex:新的条目紧随之前的索引值
    • prevLogTerm:prevLogIndex条目对应的任期号
    • entries[]:准备让对方存储的条目,如果是心跳RPC则为空
    • leaderCommit:领导人已经提交日志的索引值
  • 返回值
    • term:对应群众节点的当前任期
    • success:如果群众的日志可以和prevLogIndex以及prevLogTerm匹配的话,返回true
  • 对应群众节点应该实现的部分
    • 如果领导人的任期小于自己存储的当前任期,返回false
    • 如果本节点日志中不包含prevLogIndex或者日志任期和prevLogTerm不符合,返回false
    • 如果已经存在的日志条目和新的产生冲突(索引值相同但是任期号不同),删除这一条和之后所有的
    • 附加日志中尚未存在的任何新条目
    • 如果 leaderCommit > commitIndex,令 commitIndex 等于 leaderCommit 和 新日志条目索引值中较小的一个

总结

这两个RPC都是Raft用来保持一致性的手段,拉票和日志复制。这里的RPC可以理解成一种远程控制,有成功和失败两种状态,也分成以下两种情况讨论:

  • 我把我信息都告诉你,你愿不愿意跟我
  • 我把我信息都告诉你,你要不要和我同步

以上的”愿不愿意“,都取决于领导人/候选人给的参数和群众自身状态参数的匹配情况。

以上内容部分参考Raft论文中文译文