2

etcd/raft code walkthrough

 2 years ago
source link: https://ggaaooppeenngg.github.io/zh-CN/2018/12/11/etcd-raft-code-walkthrough/
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.

etcd/raft code walkthrough

发表于

2018-12-11 更新于 2019-08-14

Disqus: 0 Comments

我照着 raft 论文重新过了一遍 etcd/raft 的代码,主要的文件是 etcd 下面的 raft.go。对照这个代码重新梳理一遍也算是深入理解一下 raft 算法。接下来会包含两个视频一个是选举相关的内容,一个是日志复制的内容,我 walktrough 的时候默认是大致读过论文的,对一些机制和字段都有了解,没有具体解析每个字段的来历,并且把一些问题按照代码的顺序重新理了一遍。

第一部分是关于选举的,raft 本身是一个 quorum based 的算法,一致性要靠“大多数人”的同意,并且为了简单和不必要的竞争,raft 只有一个主节点,在收到大多数人的投票以后成为主节点。

第二部分是关于日志复制的,raft 需要让主节点把客户端的请求复制到大多数节点上才能算达成一致,并且 commit,下面介绍的是复制的机制,并且 ConfChange 和 Snapshot 也是走这个流程达成一致的。

之后的 walkthrough 应该会慢慢补上,关于一些其他的逻辑和具体的一些函数的细节部分会在后面放出。

v2 版本的实现存在 watcher 丢失或者丢失事件的问题,导致客户端要重新获取一遍。新版本是有本地嵌入式的数据库来避免这些问题。
mvcc 是 etcd v3 版本的存储实现主要有两个部分,一个是 backend 的 boltDB 和内存索引 key index。

BoltDB 是一个 B+ 树的嵌入式 KV store,相对于 leveldb 适用于写多读少的情况,我之前的文章简单介绍了一下 leveldb 的设计,BoltDB 比较适合读多写少,或者存在大范围 scan 的情况下比较合适,还有类似 levedb 的产品 badger,是纯 Go 实现的,在多写的情况下 leveldb 的衍生品表现更好。

BatchTx 就是收集很多的 call,然后在一个 Update 里面完成。

backend 里面存的 key 是 revision ,其中 main revision 是事务编号,sub revision 是事务中操作的编号,etcd 在 boltdb 上还做了一层缓存,所以多了一些锁机制。
内存索引中存的是真正的 key 到 revison 的索引。

key_index -> tx_buffer -> boltdb.tx

kv:
WriteView 是一些直接操作
ReadView
Read() TxnRead
Write() TxnWrite 是拿到对应的 transaction

revision:
main
sub
kvstore:
readView readView{kv} 用了 Read() Read/Write 是 kvstore 自己实现的用于拿 backend 的和自己的各种锁。(kvstore\_txn.go)
writeView writeView{kv} 用了 Write()
treeIndex:
keyIndex


writeView:
拿到 kv 的 Write(storeTxnWrite): 首先查 tw.s.kvindex.Get 然后再 backend.Tx UnsageSeqPut,然后更新 keyindex,append changes,处理 lease (old detach new attach)
readView
storeTxnRead: keyindex Revisons -> tx.UnsafeRange

lessor lesor(重音在后面)
leaseBucket 在单独的一个 bucket 里面

Recommend

  • 67
    • www.opscoder.info 6 years ago
    • Cache

    etcd中的raft实现 | jasper的blog

    在之前的一篇文章中我们了解了怎么使用ectd的raft的库来实现一个简单的分布式存储,但是只看了应用端对raft的调用以及周边,但是对于raft的库的内部没有做涉及,那么这篇文章我们就深入到raft内部看看其实现的细节。

  • 17
    • zhuanlan.zhihu.com 3 years ago
    • Cache

    etcd-raft 源码分析

    etcd-raft 源码分析gushitong人类的悲欢并不相通,我只觉得他们吵闹本篇文章主要分析et...

  • 6
    • www.codedump.info 2 years ago
    • Cache

    Etcd Raft库的工程化实现

    Etcd Raft库的工程化实现 2021-05-15 分布式 ...

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

    Etcd Raft库的日志存储

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

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

    etcd-raft (3): Raft的启动与选主

    上一篇讲了etcd-raft的日志和消息数据结构及其实现,本文就深入它对于Raft协议的实现,这一次挑选的是选主。 2. 节点启动 在看选主前,首先看下etcd-raft是如何启动的。 2.1. 数据结构 这里涉及到的数据...

  • 4
    • keys961.github.io 2 years ago
    • Cache

    etcd-raft (7): Raft线性一致读

    这里最后说明一下论文的最后部分“线性一致读”在etcd的实现。 2. 线性一致 CAP中的C即线性一致,它指的是:系统写操作提交成功后,之后的读取都会得到最新的数据。 即:在分布式系统上实现寄存器语义...

  • 7
    • keys961.github.io 2 years ago
    • Cache

    etcd-raft (1): 基于Raft的K-V存储样例

    Raft论文之前读过(Paxos这个读不懂的),也做过一定的练习实现,不过那个有点naive了,真要看还得看大名鼎鼎的etcd-raft。 不过这里先不看etcd-raft的具体实现,本文先从它提供的raftexample入手,它基于etcd-raft实现了简单的分布式K-V...

  • 6
    • keys961.github.io 2 years ago
    • Cache

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

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

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

    etcd-raft (4): Raft的复制和心跳

    上一篇讲了etcd-raft的选主协议,这次探究一下另一个重要协议:复制和心跳。 2. 日志复制 选主好了后,Leader就可以同步日志到Follower上。这里涉及到的消息类型有:MsgProp, MsgApp, MsgAppResp。

  • 7
    • keys961.github.io 2 years ago
    • Cache

    etcd-raft (6): Raft快照

    上一篇讲了etcd-raft的集群配置变更。本文顺着论文讲快照。 2. 快照内容 etcd-raft的快照内容会这么选择: 假如unstable中存在了快照,返回它保存的 否则返回Storage中的快照

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK