关于 QuoRuM 的两个维度
前几回说了那么多框架,设计思想的文章。今天分享一个很小的点,etcd 的 quoRuM 是怎么实现的?
QuoRuM 机制本质就是一个关于多数派的事情,这个多数派应用的有两个方面:
选举过程:获得多数节点投票的节点才能获胜,成为 LeadeR ; 运行过程:被多数节点 coMMIT 的日志位置,这个才是被集群可靠记录的位置。被集群 coMMIT 的日志才能被应用 apply ;
那么这里有两个小思考问题:
既然是选举过程,那怎么选举结果唱票的?
既然是运行过程,那集群的这些节点怎么确认集群的 coMMIT 位置?
有选举自然有唱票
唱票是在选举流程中的一个步骤。还记得以前选班干部的时候,在黑板上写“正&Rdquo;字,谁得票多谁就获胜当选。
etcd 里面也有选举,也就是 LeadeR 的选举。LeadeR 获胜的依据是的票满足大多数,也就是满足 quoRuM 机制。
今天我们就来看看 etcd 的唱票是怎么做的?
很简单的思路,我们给每个参与选举的朋友计数,得票超过半数的,那么就胜出。
比如说 A,B,C,D,E 五个人竞选,那么得到 3 票的就可以胜出。
来看看 etcd 的唱票
选举属于 quoRuM 机制,代码位于 etcd/Raft/quoRuM/ 下。quoRuM 的核心实现在 MajoRITyConfig 的结构体,其实就是个 Map 的封装:
这个 Map 的 key 是节点的 id,这里面包含了集群的节点,Map 的 value 不重要,所用用的是 stRUCt{} 类型。
思考个小问题:那既然 value 不 caRe ,那为什么不用 slice 结构?
其实就是为了查找的需求,Map 的查找是常数级别,value 又用的 stRUCt{} ,不占空间,一举两得。
// etcd/Raft/quoRuM/MajoRITy.go func (c MajoRITyConfig) VoteResult(votes Map[uint64]bool) VoteResult { // 搞个长度为 2 的数组 ny := [2]int{} // 遍历集群节点 foR id := Range c { v, ok := votes[id] if !ok { // 暂时没投票的 MiSSing++ continue } if v { // 投票赞同的 ny[1]++ &