ETCD 源码学习--Raft 选举的 Quorum 机制实现(七)

在 ETCD 源码学习过程,不会讲解太多的源码知识,只讲解相关的实现机制,需要关注源码细节的朋友可以自行根据文章中的提示,找到相关源码进行学习。

Quorum 相关介绍参考:https://blog.csdn.net/wxb880114/article/details/81604245

Quorum 在 etcd 中主要作用有两个,一是计算已被多数节点接收(Match) 的 Index。二是在进行 Leader 选举时,计算选举结果。

主要文件

/raft/quorum/majority.go    多数算法的实现。

/raft/quorum/joint.go    包含两个 majority 的结构体。第二暂时保留,当需要用的时候才会填充。 但 majority 的操作,会在 joint 重新实现,主要是变成操作两个 majority。

/raft/quorum/quorum.go    定义 quorum 的一些参数和数据结构。

源码实现

majority 数据结构

 type MajorityConfig map[uint64]struct{}  //MajorityConfig的定义其实就是节点集合。

计算已被多数节点接收(Match) 的 Index

func (c MajorityConfig) CommittedIndex(l AckedIndexer) Index {
	n := len(c)
	if n == 0 {
		return math.MaxUint64
	}
	// stk 会在编译时生成,如果节点数不超过7,优先使用这个,效率会更高。
	// 当节点数超过7个,使用 srt(动态生成)
	var stk [7]uint64
	var srt []uint64
	if len(stk) >= n {
		srt = stk[:n]
	} else {
		srt = make([]uint64, n)
	}

	{
		i := n - 1
		for id := range c {
			if idx, ok := l.AckedIndex(id); ok {
				srt[i] = uint64(idx)
				i--
			}
		}
	}
	/*
		这里有个程序小技巧。
		插入排序, 假如有五个节点,已匹配的节点 MatchIndex 分别是 5、3、4、2、1
		排序的结果为
			1
			2
			3
			4
			5
		n-(n/2+1) = 5-(5/2-1) = 2;
		那么多数节点已配备的Match 就是数组中索引位置为2的Match
	*/
	insertionSort(srt)
	pos := n - (n/2 + 1)
	return Index(srt[pos])
}

quorum.go 定义 AckedIndexer

type AckedIndexer interface {
	AckedIndex(voterID uint64) (idx Index, found bool)
}

/raft/tracker/tracker.go 具体实现 AckedIndexer

type matchAckIndexer map[uint64]*Progress

var _ quorum.AckedIndexer = matchAckIndexer(nil)

// AckedIndex implements IndexLookuper.
func (l matchAckIndexer) AckedIndex(id uint64) (quorum.Index, bool) {
	pr, ok := l[id]
	if !ok {
		return 0, false
	}
	return quorum.Index(pr.Match), true
}

计算 Leader 选举结果

func (c MajorityConfig) VoteResult(votes map[uint64]bool) VoteResult {
	if len(c) == 0 {

		return VoteWon
	}
	/*
		ny[0] 累计投票给当前节点的总数
		ny[1] 累计拒绝投票给当前节点的总数
	*/
	ny := [2]int{}

	var missing int
	for id := range c {
		v, ok := votes[id]
		if !ok {
			missing++
			continue
		}
		if v {
			ny[1]++
		} else {
			ny[0]++
		}
	}
	q := len(c)/2 + 1
	//超过一半则选举成功
	if ny[1] >= q {
		return VoteWon
	}
	//等待其他节点投票
	if ny[1]+missing >= q {
		return VotePending
	}
	//选举失败
	return VoteLost
}

在进行Leader选举时, /ratf/tracker/tracker.go  会通过  TallyVotes 调用该函数,计算选举结果。

joint 数据结构

type JointConfig [2]MajorityConfig

JointConfig 与 MajorityConfig 实现的功能相似,只是从计算一个 MajorityConfig 变成 计算两个 MajorityConfig。

 

PS:欢迎纠正

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值