面试官:聊聊 etcd 中的 Raft 吧
Raft:(computer_science "Raft") 是近年来比较流行的一个一致性算法 。 它的原理比较容易理解 , 网上也有很多相关的介绍 , 因此这里我就不再啰嗦原理了 , 而是打算以 raft 在 etcd 中的实现1[1]为例 , 从工程的角度来讲讲这个算法的一个具体实现 , 毕竟了解原理只算是“纸上谈兵” , 离真正能把它应用起来还有很长一段距离 。
如果你还不熟悉 raft , 这个经典的动画演示[2]、它的论文[3]以及这个 lecture[4]可能会对你有帮助 。 或者你也可以直接观看下面的视频 , 这是我作的一次技术分享 , 讲的是etcd 中 raft 模块的源码解析[5] 。 说句题外话 , 很多 Conference 和 Meetup 都会把视频录像上传到 YouTube 上 , YouTube 简直就是程序员的衣柜 , 每逛一次都有新收获 。 (方便播放 , 放一个 B 站链接)
Overview【面试官:聊聊 etcd 中的 Raft 吧】Etcd 将 raft 协议实现为一个 library , 然后本身作为一个应用使用它 。 当然 , 可能是为了推广它所实现的这个 library , etcd 还额外提供了一个叫raftexample[6] 的示例程序 , 向用户展示怎样在它所提供的 raft library 的基础上构建出一个分布式的 KV 存储引擎 。
在 etcd 中 , raft 作为底层的共识模块 , 运行在一个goroutine里 , 通过channel接受上层(etcdserver)传来的消息 , 并将处理后的结果通过另一个channel返回给上层应用 , 他们的交互过程大概是这样的:
文章插图
Raft Stack
这种全异步的交互方式好处就是它提高了性能 , 但坏处就是难以调试 , 代码看起来会很绕 。 拿 etcd 举例 , 很多时候你只看到它把一个消息 push 到一个 slice/channel 里面 , 然后这部分函数调用链就结束了 , 你无法直观的追踪到 , 到底是谁最后处理了这个消息 。
Code Breakdown我们来看一下这个 raft library 里面都有哪些文件:
$ tree --dirsfirst -L 1 -I '*test*' -P '*.go'.├── raftpb├── doc.go├── log.go├── log_unstable.go├── logger.go├── node.go├── progress.go├── raft.go├── rawnode.go├── read_only.go├── status.go├── storage.go└── util.go
下面按功能模块依次介绍:
raftpbRaft 中的序列化是借助于Protocol Buffer[7]来实现的 , 这个文件夹就定义了需要序列化的几个数据结构 , 我们先从Entry和Message开始看起:
Entry从整体上来说 , 一个集群中的每个节点都是一个状态机 , 而 raft 管理的就是对这个状态机进行更改的一些操作 , 这些操作在代码中被封装为一个个Entry 。
// #L203type Entry struct {Termuint64Indexuint64TypeEntryTypeData[]byte}
- Term:选举任期 , 每次选举之后递增 1 。 它的主要作用是标记信息的时效性 , 比方说当一个节点发出来的消息中携带的 term 是 2 , 而另一个节点携带的 term 是 3 , 那我们就认为第一个节点的信息过时了 。
- Index:当前这个 entry 在整个 raft 日志中的位置索引 。 有了Term和Index之后 , 一个 log entry 就能被唯一标识 。
- Type:当前 entry 的类型 , 目前 etcd 支持两种类型:EntryNormal[8]和EntryConfChange[9] , EntryNormal 代表当前 Entry 是对状态机的操作 , EntryConfChange 则代表对当前集群配置进行更改的操作 , 比如增加或者减少节点 。
- Data:一个被序列化后的 byte 数组 , 代表当前 entry 真正要执行的操作 , 比方说如果上面的Type是EntryNormal , 那这里的 Data 就可能是具体要更改的 key-value pair , 如果Type是EntryConfChange , 那 Data 就是具体的配置更改项ConfChange[10] 。 raft 算法本身并不关心这个数据是什么 , 它只是把这段数据当做 log 同步过程中的 payload 来处理 , 具体对这个数据的解析则有上层应用来完成 。
推荐阅读
- 聊聊网易云音乐:“心动模式”
- 华为突然宣布!腾讯也没有想到,一切来得如此快
- 全球最受欢迎的4部5G手机:靠量取胜的小米竟榜上无名?
- Java学习:Java学习到什么程度可以进行面试
- 程序员面试金典17.05_go_字母与数字
- 安卓春招面经:二本渣院面试网易被拒,最终获腾讯阿里offer
- 中国最赚钱的公司诞生!不是移动,也不是阿里巴巴,那第一是?
- 「6」进大厂必须掌握的面试题-Hibernate
- 高通骁龙888提前来了!华为“慌”了?但一切还没有定论
- 震惊!京东T4大佬面试整整三个月,才写了两份java面试笔记