Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

发现更大的ballot number,应该退出这个prepare而不是继续? #26

Open
zhoupingjay opened this issue Apr 8, 2022 · 5 comments

Comments

@zhoupingjay
Copy link

在 Phase1() 中,按照协议 proposer 在遇到更高的 ballot number 时,即说明prepare失败,但代码里似乎仍会继续(continue):

continue

	for _, r := range replies {

		pretty.Logf("Proposer: handling Prepare reply: %s", r)
		if !p.Bal.GE(r.LastBal) {
			if r.LastBal.GE(&higherBal) {
				higherBal = *r.LastBal
			}
			continue   // <-- prepare失败后仍然继续?
		}

		// find the voted value with highest vbal
		if r.VBal.GE(maxVoted.VBal) {
			maxVoted = r
		}

		ok += 1
		if ok == quorum {
			return maxVoted.Val, nil, nil
		}
	}

考虑这样的情况:假设有5个reply,quorum=3, 其中1个回答了更高的ballot number,而有4个回答了比 proposer 低的 ballot number。按照上面的代码,会得到 ok==4,成功达到quorum进入phase 2?这里的continue是否应该改成break?

@drmingdrmer
Copy link
Member

依旧continue, ok==4 时可以形成多数, 还可以继续提交.

协议里说的不太清楚, 遇到更高的ballot时,可能很大概率无法成功了, 所以及时终止比较好.

@zhoupingjay
Copy link
Author

嗯……我想是不是可以这样理解:

在phase-1遇到更高的ballot number,但是其数量并没有影响我拿到quorum(比如我问了所有5个节点,1个有更高的ballot number,其余4个都比我低)。这种情况说明可能有其他的proposer用更高的ballot number尝试过phase-1,但失败了(否则他就会拿到多数派的promise,从而我不可能拿到quorum)。这种情况下,我可以有两种选择:

(1) 一是严格按照经典paxos协议,认为我的这次phase-1失败了,退出并用更高的ballot number重新尝试。

(2) 二是既然我能够拿到quorum,说明其他proposer的phase-1没成功(即使它用了更高的ballot number),这时我继续往下执行phase-2提交,不会造成不一致的情况。

但是这样的话,那些已经promise过更高ballot number的acceptor,要怎么处理我发来的Accept消息呢?对这些acceptor来说,既然已经promise了更高的ballot number,就应该拒绝这个Accept请求(参见这里的slide-31)。于是这些promise过更高ballot number的acceptor都会拒绝我的Accept请求。这不会影响正确性,因为这些拒绝我Accept请求的acceptor是少数(否则我不会进入phase-2)。所以这些其实是无效的promise。这种情况也不会永远持续下去,因为ballot number是单调增加的,当协议运行到采用更高ballot number时,这些无效的promise就会被override掉。

总结一下,选项 (1) 按照经典paxos直接失败退出phase-1更加简单,但代价就是需要重新做phase-1,选项 (2) 可以避免一次重复的phase-1,但逻辑上这两者是等价的,(2) 相当于把 (1) 后面的重试phase-1合并进来了。

@drmingdrmer
Copy link
Member

但是这样的话,那些已经promise过更高ballot number的acceptor,要怎么处理我发来的Accept消息呢?

嗯. 拒绝就行了

总结一下,选项 (1) 按照经典paxos直接失败退出phase-1更加简单,但代价就是需要重新做phase-1,选项 (2) 可以避免一次重复的phase-1,但逻辑上这两者是等价的,(2) 相当于把 (1) 后面的重试phase-1合并进来了。

总结的挺好的:D

@cquliaoli
Copy link

嗯……我想是不是可以这样理解:

在phase-1遇到更高的ballot number,但是其数量并没有影响我拿到quorum(比如我问了所有5个节点,1个有更高的ballot number,其余4个都比我低)。这种情况说明可能有其他的proposer用更高的ballot number尝试过phase-1,但失败了(否则他就会拿到多数派的promise,从而我不可能拿到quorum)。这种情况下,我可以有两种选择:

(1) 一是严格按照经典paxos协议,认为我的这次phase-1失败了,退出并用更高的ballot number重新尝试。

(2) 二是既然我能够拿到quorum,说明其他proposer的phase-1没成功(即使它用了更高的ballot number),这时我继续往下执行phase-2提交,不会造成不一致的情况。

但是这样的话,那些已经promise过更高ballot number的acceptor,要怎么处理我发来的Accept消息呢?对这些acceptor来说,既然已经promise了更高的ballot number,就应该拒绝这个Accept请求(参见这里的slide-31)。于是这些promise过更高ballot number的acceptor都会拒绝我的Accept请求。这不会影响正确性,因为这些拒绝我Accept请求的acceptor是少数(否则我不会进入phase-2)。所以这些其实是无效的promise。这种情况也不会永远持续下去,因为ballot number是单调增加的,当协议运行到采用更高ballot number时,这些无效的promise就会被override掉。

总结一下,选项 (1) 按照经典paxos直接失败退出phase-1更加简单,但代价就是需要重新做phase-1,选项 (2) 可以避免一次重复的phase-1,但逻辑上这两者是等价的,(2) 相当于把 (1) 后面的重试phase-1合并进来了。

假设 writer1 在 phase 1 只写入 ballot numer = 10000 到 acceptor1,writer2 通过 ballot number = 2 ,成功给其他四个 acceptor 提交了值 V,那么无论哪个 writer 只要 ballot number 小于 10000 ,都无法修改 acceptor1 的值了,此时需要用 learner 去修正 acceptor1 的值?

@drmingdrmer
Copy link
Member

假设 writer1 在 phase 1 只写入 ballot numer = 10000 到 acceptor1,writer2 通过 ballot number = 2 ,成功给其他四个 acceptor 提交了值 V,那么无论哪个 writer 只要 ballot number 小于 10000 ,都无法修改 acceptor1 的值了,此时需要用 learner 去修正 acceptor1 的值?

这时acceptor-1只有一个ballot number 10000, 因为phase-1没有达到quorum, 不会有值写入acceptor-1, 也就不需要你说的修正啦.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants