raft日志复制

why:

  raft算法中,副本数据是以日志的形式产生的。即leader收到客户端的写请求后,处理写请求的过程就是:日志复制提交的过程。

 

what:

  日志格式:

    日志是由日志项组成的,包括:用户指令(Command),索引值(log index),任期编码(term)。具体如下:

    

 

    指令:一条由客户端指定、状态机需要执行的指令;也可理解为“客户端指定的数据”;

    索引值:日志项在日志中对应的整数索引值。它是用来标记日志项在日志列表中位置的,是一个单调、递增的整数;

    任期编号:创建日志项的leader所在的任期值;

 

how:

  如何复制日志

    raft日志复制可以理解为优化后的二阶段提交(即一阶段提交替代了二阶段提交),那么就减少了1次rpc请求耗时。具体步骤如下:

    a、领导者通过日志复制 RPC,将新的日志项复制到其他的服务器。

    b、当领导者将日志项,成功复制到大多数的服务器上的时候,领导者会将这条日志项提交 到它的状态机中。

    c、领导者将执行的结果返回给客户端

    d、当跟随者接收到心跳信息,或者的日志复制 RPC 消息后,如果跟随者发现领导者已经 提交了某条日志项,而它还没提交,那么跟随者就将这条日志项提交到本地的状态机 中。

                     

 

 

 

    注意:领导者将日志项提交到它的状态,而没有通知跟随者提交?

    原因:领导 者的日志复制 RPC 消息或心跳消息,包含了当前最大的,将会被提交的日志项索引值。所以跟随者就可以知道领导者的日志提交位置信息。

 

 

  如何实现日志的一致性

    核心思想:领导者通过强制跟随者直接复制自己的日志项,处理不一致日志;

    核心有 2 个步骤:

      a、领导者通过日志复制 RPC一致性检查,找到跟随者节点上,与自己相同日志项的最大索引值。即:,这个索引值之前的日志,领导者和跟随者是一致的,之后的 日志是不一致的了。

      b、领导者强制跟随者更新覆盖不一致日志项,实现日志的一致。

    注意:跟随者中的不一致日志项被领导者的日志覆盖,而且领导者 从来不会覆盖或者删除自己的日志。

 

    具体过程如下:

      PrevLogEntry:表示当前要复制日志项的前面一条日志项的索引值。比如在图中,如 果领导者将索引值为 8 的日志项发送给跟随者,那么此时 PrevLogEntry 值为 7。

      PrevLogTerm:表示当前要复制日志项的前面一条日志项的任期编号。比如在图中, 如果领导者将索引值为 8 的日志项发送给跟随者,那么此时 PrevLogTerm 值为 4。

    

 

 

    

     

 

     

 

 

    a、领导者通过日志复制 RPC 消息,发送当前最新日志项到跟随者 ,例如:这个消息的 PrevLogEntry 值为 7,PrevLogTerm 值 为 4。

    b、如果跟随者在它的日志中,找不到与 PrevLogEntry 值为 7、PrevLogTerm 值为 4 的日 志项。也就是说:它的日志和领导者的不一致了,那么跟随者就会拒绝接收新的日志项, 并返回失败信息给领导者。

    c、这时,领导者递减要复制的日志项的索引值,并发送新的日志项到跟随者。即:消息 的 PrevLogEntry 值为 6,PrevLogTerm 值为 3。

    d、如果跟随者在它的日志中,找到了 PrevLogEntry 值为 6、PrevLogTerm 值为 3 的日志 项,那么日志复制 RPC 返回成功。则:领导者就知道在 PrevLogEntry 值为 6、 PrevLogTerm 值为 3 的位置,跟随者的日志项与自己相同。

    e、领导者通过日志复制 RPC,复制并更新覆盖索引值之后的日志项(也就是不一致的日 志项),最终实现了集群各节点日志的一致。

  

 

posted @ 2022-03-21 23:57  修心而结网  阅读(181)  评论(0编辑  收藏  举报