Skip to content

Commit

Permalink
r/vote: do not wait for majority of responses from unique voters
Browse files Browse the repository at this point in the history
In joint consensus raft needs majority of both new and previous quorums
to make the decisions. Voting for new leader is one of the processes
that requires majority agreement from both quorums. In previous
implementation we waited for majority of the vote request responses.
This approach would make leader election much slower in situations where
quorums differ by one node.

Example:

current voters: `[1,2,4]`, previous voters: `[1,2,3]`

In this scenario to elect leader it is enough to wait from responses
from node 1 and 2 as they form majority in both quorums. In previous
implementation we wait for at least `(n/2)+1` responses. Where `n` is a
number of unique voter ids. In the example above `n = len([1,2,3,4]) =
4`. This way we had to wait for 3 replies while only 2 of the are enough
to elect new leader.

Changed implementation to check if we can make a definitive decision
about vote round result after receiving each of the replies. This way we
will always use smallest possible set of replies to make a decision.

Signed-off-by: Michal Maslanka <michal@vectorized.io>
(cherry picked from commit bca6f1d)
  • Loading branch information
mmaslankaprv authored and dotnwat committed Apr 6, 2022
1 parent bf95566 commit 018f358
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 19 deletions.
9 changes: 2 additions & 7 deletions src/v/raft/prevote_stm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -163,13 +163,8 @@ ss::future<bool> prevote_stm::do_prevote() {
// dispatch requests to all voters
_config->for_each_voter([this](vnode id) { (void)dispatch_prevote(id); });

// wait until majority
const size_t majority = (_config->unique_voter_count() / 2) + 1;

return _sem.wait(majority)
.then([this] { return process_replies(); })
// process results
.then([this]() { return _success; });
// process results
return process_replies().then([this]() { return _success; });
}

ss::future<> prevote_stm::process_replies() {
Expand Down
17 changes: 5 additions & 12 deletions src/v/raft/vote_stm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -144,18 +144,11 @@ ss::future<> vote_stm::do_vote() {
// dispatch requests to all voters
_config->for_each_voter([this](vnode id) { (void)dispatch_one(id); });

// wait until majority
const size_t majority = (_config->unique_voter_count() / 2) + 1;

return _sem.wait(majority)
.then([this] { return process_replies(); })
// porcess results
.then([this]() {
return _ptr->_op_lock.get_units().then(
[this](ss::semaphore_units<> u) {
return update_vote_state(std::move(u));
});
});
return process_replies().then([this]() {
return _ptr->_op_lock.get_units().then([this](ss::semaphore_units<> u) {
return update_vote_state(std::move(u));
});
});
}

ss::future<> vote_stm::process_replies() {
Expand Down

0 comments on commit 018f358

Please sign in to comment.