12

聊聊Raft的一个实现(2)-日志提交

 4 years ago
source link: http://vearne.cc/archives/1439
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
版权声明 本站原创文章 由 萌叔 发表
转载请注明 萌叔 | http://vearne.cc

在我的上一篇文章聊聊Raft的一个实现(1),我简要的介绍了 goraft/raftd。这篇文章我将结合goraft的实现,来聊聊raft中的一些场景

2. 场景1-正常的执行1条WriteCommand命令

在上一篇文章,我们已经提到WriteCommand和NOPCommand、JoinCommand一样,对goraft而言都是LogEntry, 执行它时,这条命令会被分发到整个Cluster,让我们看看其中的详细过程

当前我们有3个node

节点 state name connectionString term lastLogIndex commitIndex node1 leader 2832bfa localhost:4001 17 26 26 node2 follower 3320b68 localhost:4002 17 26 26 node3 follower 7bd5bdc localhost:4003 17 26 26

从上表可以看出整个集群处于完全一致的状态,我们开始执行WriteCommand

step1 client:通过API提交WriteCommand命令

curl -XPOST http://localhost:4001/db/aaa -d 'bbb'

step2 node1:收到指令后,生成LogEntry
1) 写入logfile (磁盘文件)
2)添加到Log.entries (内存)

step3 node1:等待Heartbeat(周期性由leader发往其它每个node1和node2), 把LogEntry带给其它node(这里的node1,node2状态相同,所以AppendEntriesRequest是一样的)
AppendEntriesRequest

{
    "Term": 17,
    "PrevLogIndex": 26, 
    "PrevLogTerm": 17,
    "CommitIndex": 26,
    "LeaderName": "2832bfa",
    "Entries": [{
        "Index": 27,
        "Term": 17,
        "CommandName": "write",
        "Command": "eyJrZXkiOiJhYWEiLCJ2YWx1ZSI6ImJiYiJ9Cg=="
    }]
}

这里对PrevLogIndex做下简单的解释,PrevLogIndex表示的是leader所认为的followerleader保持一致的最后一个日志index。PrevLogTerm是与PrevLogIndex对应的term
Command做了base64编码解码后

{
    "key": "aaa",
    "value": "bbb"
}

现在解释下上面的AppendEntriesRequest,node1(leader)告诉node2(follower)

如果LogIndex 26, 咱们是一致的, 那么Append LogIndex 27

注释: 如果node2(follower) 的情况与node1(leader)了解的一致,那么它就执行Append, 否则会拒绝, 并告知实际情况

step4 node2:收到 AppendEntriesRequest后,提取出LogEntry
1) 写入logfile (磁盘文件)
2)添加到Log.entries (内存)
发出AppendEntriesResponse

{
    "Term": 17,
    "Index": 27, 
    "CommitIndex": 26,
    "Success": true
}

step5 node1:收到node2 发出AppendEntriesResponse后,由于这个cluster一共只有3个node,那么已经2个node完成了Append动作,下面可以执行Commit动作。
node1 将 {“key”:”aaa”,”value”:”bbb”} 插入内存数据库

step6 node1:等待Heartbeat将Commit消息通知给其它节点。
AppendEntriesRequest

{
    "Term": 17,
    "PrevLogIndex": 27,
    "PrevLogTerm": 17,
    "CommitIndex": 27, 
    "LeaderName": "2832bfa",
    "Entries": null
}

step7 node2收到AppendEntriesRequest后
将 {“key”:”aaa”,”value”:”bbb”} 插入自己的内存数据库
返回AppendEntriesResponse

{
    "Term": 17,
    "Index": 27,
    "CommitIndex": 27,
    "Success": true
}

这些步骤都执行完成以后,WriteCommand命令才算是在整个cluster中执行完成,你可以使用

curl http://localhost:4002/db/aaa

查看aaa对应的值。
node3 与node2的情况完全一致,所以这里不再赘述。

完整日志

  1. 可以很明显的看出Append动作和Commit动作是两个完全不同的动作。
  2. 只要client等到leader完成Commit动作。即使后续leader发生变更或部分节点崩溃,raft协议可以保证,client所提交的改动依然有效。

raft非常的复杂,聊聊Raft的一个实现可能会成为一个比较长的系列


如果我的文章对你有帮助,你可以给我打赏以促使我拿出更多的时间和精力来分享我的经验和思考总结。

微信支付码

Recommend

  • 83
    • zhuanlan.zhihu.com 7 years ago
    • Cache

    Elasticell-Multi-Raft实现

    Elasticell-Multi-Raft实现fagongziElasticell, Gateway项目作者

  • 32
    • 微信 mp.weixin.qq.com 6 years ago
    • Cache

    图解Raft之日志复制

  • 32
    • qeesung.github.io 4 years ago
    • Cache

    Raft 算法之日志复制

  • 10

    聊聊raft的一个实现(3)–commit 版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 我在 聊聊raft的一个实...

  • 13

    聊聊Raft的一个实现(1)–goraft 版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 最近花了不少时间来学习raft相关的知识,写这篇文章的目的 ...

  • 13

    ▲  点击上方"多颗糖" 关注公众号 在上篇《条分缕析 Raft 算法》中推导和梳理了 Raft 算法,但仍有一些细节没有包含到,这篇文章作为补充。 1 日志压缩 随着时间推移,存...

  • 7

    上次讲到 Raft 领导者选举:「图解 Raft 共识算法:如何选举领导者?」,接着这个话题继续跟大家聊下关于 Raft 日志复制的一些细节。 Raft 日志格式 在 Raft 算法中,需要...

  • 10
    • vearne.cc 3 years ago
    • Cache

    聊聊Raft协议

    版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 1. 参考资料 The original project authors have created new raft implementations now used in etcd and InfluxDB.

  • 8
    • www.codedump.info 3 years ago
    • Cache

    Etcd Raft库的日志存储

    之前看etcd raft实现的时候,由于wal以及日志的落盘存储部分,没有放在raft模块中,对这部分没有扣的特别细致。而且,以前我的观点认为etcd raft把WAL这部分留给了上层的应用去实现,自身通过Ready结构体来通知应用层落盘的数据,这个观点也有失偏...

  • 9
    • keys961.github.io 3 years ago
    • Cache

    etcd-raft (2): Raft日志与消息

    Raft中的一个重要组件就是日志,另一个比较重要的是Raft节点传输的消息。 在etcd中,日志的实现是raftLog,消息的定义是Message。本文就看下这些组件的实现。 2. Raft日志 etcd-raft的Raft日志由raf...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK