1120 Commits

Author SHA1 Message Date
Pavel Kalinnikov
4969aa81ae raft: send empty appends when replication is paused
When Inflights to a particular node is full, i.e. MaxInflightMsgs for the
append messages flow is saturated, it is still necessary to continue sending
MsgApp to ensure progress. Currently this is achieved by "forgetting" the first
in-flight message in the window, which frees up quota for one new MsgApp.

This new message is constructed in such a way that it potentially has multiple
entries, or a large entry. The effect of this is that the in-flight limitations
can be exceeded arbitrarily, for as long as the flow to this node continues
being saturated. In particular, if a follower is stuck, the leader will keep
sending entries to it.

This commit makes the MsgApp empty when Inflights is saturated, and prevents
the described leakage of Entries to slow followers.

Signed-off-by: Pavel Kalinnikov <pavel@cockroachlabs.com>
2022-11-08 22:21:39 +00:00
Pavel Kalinnikov
3bc3d2071e raft: extract Progress update on MsgApp to a method
Previously, Progress update on MsgApp send was scattered across raft.go and
tracker/progress.go. This commit better encapsulates this logic in the Progress
type.

Signed-off-by: Pavel Kalinnikov <pavel@cockroachlabs.com>
2022-11-08 22:21:38 +00:00
Pavel Kalinnikov
d5ac7b833f raft: cleanup maybeSendAppend method
- avoid large indented blocks, leave the main block unindented
- declare pb.Message inlined in the sending call

Signed-off-by: Pavel Kalinnikov <pavel@cockroachlabs.com>
2022-11-08 22:21:38 +00:00
Pavel Kalinnikov
5619953f33 raft: elaborate checks in flow control tests
Signed-off-by: Pavel Kalinnikov <pavel@cockroachlabs.com>
2022-11-08 22:21:38 +00:00
Pavel Kalinnikov
0a0f0ae719 raft/rafttest: add test for replication pausing
This commit adds a data-driven test which simulates conditions under which Raft
messages flow to a particular node is throttled while in StateReplicate. The
test demonstrates that MsgApp messages with non-empty Entries may "leak" to a
paused stream every time there is successful heartbeat exchange.

Signed-off-by: Pavel Kalinnikov <pavel@cockroachlabs.com>
2022-11-08 22:21:38 +00:00
Marek Siarkowicz
2a1055c7f3 raft: Remove dependency on etcd api
Signed-off-by: Marek Siarkowicz <siarkowicz@google.com>
2022-11-08 13:56:46 +01:00
Benjamin Wang
fe7da79594 raft: remove the raft dependency on go.etcd.io/etcd/client/pkg/v3
Signed-off-by: Benjamin Wang <wachao@vmware.com>
2022-11-08 09:20:19 +08:00
Benjamin Wang
f64bed6033
Merge pull request #14698 from ahrtr/raft_warn_20221107
raft: change the log from debug to warning when uncommitted size exceeds threshold
2022-11-07 19:57:33 +08:00
Benjamin Wang
3e07097d77
Merge pull request #14545 from nvanbenschoten/nvanbenschoten/simplifyAutoLeave
raft: simplify auto-leave joint config on entry application logic
2022-11-07 17:20:26 +08:00
Benjamin Wang
a671e3ebd1 raft: change the log from debug to warning when uncommitted size exceeds max threshold
Signed-off-by: Benjamin Wang <wachao@vmware.com>
2022-11-07 17:17:48 +08:00
王霄霄
aac5feec94 raft: remove duplicate letter in comment.
Signed-off-by: Wang Xiaoxiao 1141195807@qq.com
Signed-off-by: 王霄霄 <1141195807@qq.com>
2022-10-22 19:13:40 +08:00
Nathan VanBenschoten
419ee8a9c6 raft: panic on self-addressed messages
These are nonsensical and a network implementation is not required
to handle them correctly, so panic instead of sending them out.

Signed-off-by: Nathan VanBenschoten <nvanbenschoten@gmail.com>
2022-10-06 20:25:07 -04:00
Nathan VanBenschoten
c50e728518 raft: simplify auto-leave joint config on entry application logic
This commit simplifies the logic added in 37c7e4d to auto-leave joint
configurations. It does so by making the following adjustments to the
code:

- remove the `oldApplied <= r.pendingConfIndex` condition. This does
  not seem necessary. When a node first attempts to auto-leave a joint
  config, it will bump `r.pendingConfIndex` when proposing. In cases
  where `oldApplied >= r.pendingConfIndex`, the proposal must have
  already been applied. Reviewers should double check this.
- use raft.Step instead of custom proposal code. This code was already
  present in stepLeader, so there was no reason to duplicate it. This
  would have avoided bugs like the one we fixed in #14538.
- use `confChangeToMsg` to generate message, to centralize the creation
  of all `MsgProp{EntryConfChange}` messages.

Signed-off-by: Nathan VanBenschoten <nvanbenschoten@gmail.com>
2022-10-03 02:11:56 -04:00
Benjamin Wang
a932fb58f2
Merge pull request #14539 from nvanbenschoten/nvanbenschoten/advanceHardState
raft: update prevHardSt on Ready accept, not advance
2022-09-30 16:55:45 +08:00
Nathan VanBenschoten
bd34388721 raft: broadcast MsgApp on auto-leave joint config proposal
This commit ensures that the raft leader eagerly broadcasts a MsgApp to
each follower when initiating an automatic transition out of a joint
configuration. This had been missed previously, which could lead to
delayed completion of an auto-transition.

Signed-off-by: Nathan VanBenschoten <nvanbenschoten@gmail.com>
2022-09-29 12:33:20 -04:00
Nathan VanBenschoten
9a03632043 raft: update prevHardSt on Ready accept, not advance
This commit updates the `RawNode`'s `prevHardSt` to the new HardState in
`acceptReady` instead of on `Advance`. This aligns the handling of
`prevHardSt` with that of `prevSoftSt` (and other fields like `msgs`)
and simplifies the logic in `Advance`.

Signed-off-by: Nathan VanBenschoten <nvanbenschoten@gmail.com>
2022-09-29 12:33:04 -04:00
Benjamin Wang
7f10dccbaf Bump go 1.19: update all the dependencies and go.sum files
1. run ./scripts/fix.sh;
2. cd tools/mod; gofmt -w . & go mod tidy;

Signed-off-by: Benjamin Wang <wachao@vmware.com>
2022-09-22 08:47:46 +08:00
Benjamin Wang
cd0b1d0c66 Bump go 1.19: upgrade go version to 1.19 in all go.mod files
Signed-off-by: Benjamin Wang <wachao@vmware.com>
2022-09-22 08:47:46 +08:00
Benjamin Wang
31d9664cb5
Merge pull request #14413 from tbg/raft-single-voter
raft: don't emit unstable CommittedEntries
2022-09-22 08:43:37 +08:00
Tobias Grieger
9ad36eecab fixup! address comments
Signed-off-by: Tobias Grieger <tobias.b.grieger@gmail.com>
2022-09-20 09:01:42 +02:00
Tobias Grieger
3c3e30a30e Revert "raft: directly update leader in advance"
This reverts commit d73a986e4edb15ef9dbfc994f1cbf5e96694d877, which
was added only for benchmarking purposes.

Signed-off-by: Tobias Grieger <tobias.b.grieger@gmail.com>
2022-09-20 09:01:42 +02:00
Tobias Grieger
67c3522893 raft: directly update leader in advance
This makes the alternative option of implementing the leader's self-ack
of entry append the default.

Signed-off-by: Tobias Grieger <tobias.b.grieger@gmail.com>
2022-09-20 09:01:42 +02:00
Tobias Grieger
894e5cb685 move ctx param to the front
to appease linter

Signed-off-by: Tobias Grieger <tobias.b.grieger@gmail.com>
2022-09-20 09:01:42 +02:00
Tobias Grieger
f62b9d5e19 remove TestNodeReadIndex
This is tested directly at the level of `RawNode` in
`TestRawNodeReadIndex`. `*node` is a thin wrapper around `RawNode` so
this is sufficient.

The reason to remove the test is that it now incurs data races
since it's not possible to adjust the `readStates` and `step`
fields while the node is running, and there is no primitive
to synchronize with its goroutine. This could all be fixed
but it's not worth it.

Signed-off-by: Tobias Grieger <tobias.b.grieger@gmail.com>
2022-09-20 09:01:40 +02:00
Tobias Grieger
f7dcb9ec2a TestInteraction
Reviewed the diff in detail.
The changes here were benign, just the extra raft cycle.

Signed-off-by: Tobias Grieger <tobias.b.grieger@gmail.com>
2022-09-20 08:59:37 +02:00
Tobias Grieger
f7b0a6ad33 TestRawNodeBoundedLogGrowthWithPartition
Signed-off-by: Tobias Grieger <tobias.b.grieger@gmail.com>
2022-09-20 08:59:37 +02:00
Tobias Grieger
02efe5135d TestRawNodeStart
Now also sees the extra Ready cycle.

Signed-off-by: Tobias Grieger <tobias.b.grieger@gmail.com>
2022-09-20 08:59:37 +02:00
Tobias Grieger
79bf3b0df4 TestRawNodeJointAutoLeave
This now needs an additional Ready cycle to apply the previous conf change,
so the finalizing conf change does too.

Signed-off-by: Tobias Grieger <tobias.b.grieger@gmail.com>
2022-09-20 08:59:37 +02:00
Tobias Grieger
fbe4d40086 TestLeaderTransferIgnoreProposal
Signed-off-by: Tobias Grieger <tobias.b.grieger@gmail.com>
2022-09-20 08:59:37 +02:00
Tobias Grieger
182e1a371d TestReadOnlyWithLearner
Signed-off-by: Tobias Grieger <tobias.b.grieger@gmail.com>
2022-09-20 08:59:37 +02:00
Tobias Grieger
b462fd15c2 TestMsgAppRespWaitReset
Signed-off-by: Tobias Grieger <tobias.b.grieger@gmail.com>
2022-09-20 08:59:37 +02:00
Tobias Grieger
ff837f3a0b TestProposal
Don't check on `committed` but `lastIndex` instead.

Signed-off-by: Tobias Grieger <tobias.b.grieger@gmail.com>
2022-09-20 08:59:37 +02:00
Tobias Grieger
15abe294e7 TestDueling{Pre,}Candidates
Signed-off-by: Tobias Grieger <tobias.b.grieger@gmail.com>
2022-09-20 08:59:37 +02:00
Tobias Grieger
d6f3e88a52 TestSingleNodeCommit
Signed-off-by: Tobias Grieger <tobias.b.grieger@gmail.com>
2022-09-20 08:59:37 +02:00
Tobias Grieger
99adcaa299 TestLearnerLogReplication
Needed to `(*raft).advance` on `n1` so that it would actually commit
the entry.

Signed-off-by: Tobias Grieger <tobias.b.grieger@gmail.com>
2022-09-20 08:59:37 +02:00
Tobias Grieger
7060d75527 TestLeaderOnlyCommitsLogFromCurrentTerm
Leader only acks to itself on `(*raft).advance` so we have to
make this test a bit more like the real thing.

Signed-off-by: Tobias Grieger <tobias.b.grieger@gmail.com>
2022-09-20 08:59:37 +02:00
Tobias Grieger
9ff144ef75 TestProgressLeader
This was expecting the progress of the leader to be updated as a
result of MsgProp but it is now happening in `(*raft).advance`.

Signed-off-by: Tobias Grieger <tobias.b.grieger@gmail.com>
2022-09-20 08:59:37 +02:00
Tobias Grieger
bd46776f03 Commit + apply all in nextEnts
This fixes essentially all tests using this, since now they don't have
to do anything special about the extra cycle introduced for single
nodes.

Signed-off-by: Tobias Grieger <tobias.b.grieger@gmail.com>
2022-09-20 08:59:37 +02:00
Tobias Grieger
f10579d3b5 TestLeaderAcknowledgeCommit
This needed to call `(*raft).advance` so that the leader would
self-ack the entries.

Signed-off-by: Tobias Grieger <tobias.b.grieger@gmail.com>
2022-09-20 08:59:37 +02:00
Tobias Grieger
b2dba1c86c TestNodeAdvance
Switched this to baking the conf changes into the initial state
to have fewer cycles to walk through in the test.

Signed-off-by: Tobias Grieger <tobias.b.grieger@gmail.com>
2022-09-20 08:59:37 +02:00
Tobias Grieger
0d9a6061c3 TestNodeReadIndex
Needs to ignore the injected MsgAppResp.

Signed-off-by: Tobias Grieger <tobias.b.grieger@gmail.com>
2022-09-20 08:59:37 +02:00
Tobias Grieger
14a76d755f TestNodeStart
This now sees the extra append-then-commit cycle.

Signed-off-by: Tobias Grieger <tobias.b.grieger@gmail.com>
2022-09-20 08:59:37 +02:00
Tobias Grieger
873cdf3fa6 TestNodeProposeWaitDropped
The test just needs to ignore the MsgAppResp.

Signed-off-by: Tobias Grieger <tobias.b.grieger@gmail.com>
2022-09-20 08:59:37 +02:00
Tobias Grieger
1a81b27bed TestNodePropose{,Config}
This test now observes the `MsgAppResp` injected in `(*raft).advance`.

Signed-off-by: Tobias Grieger <tobias.b.grieger@gmail.com>
2022-09-20 08:59:37 +02:00
Tobias Grieger
87a9b80d7b TestNodeProposeAddDuplicateNode
This needed to apply entries from CommittedEntries, not Entries.
Previously the test got away with it because the two slices were
equal. Now it was hanging because when it proposed the second
conf change the first one hadn't applied yet, and so it got dropped,
and the test would hang.

Signed-off-by: Tobias Grieger <tobias.b.grieger@gmail.com>
2022-09-20 08:59:37 +02:00
Tobias Grieger
931fec3b6d TestCommitPagination
Signed-off-by: Tobias Grieger <tobias.b.grieger@gmail.com>
2022-09-20 08:59:37 +02:00
Tobias Grieger
1f39a8fe79 raft: teach readyWithTimeout to log received Readys
Signed-off-by: Tobias Grieger <tobias.b.grieger@gmail.com>
2022-09-20 08:59:37 +02:00
Tobias Grieger
36860f863f TestLeaderAcknowledgeCommit
Signed-off-by: Tobias Grieger <tobias.b.grieger@gmail.com>
2022-09-20 08:59:37 +02:00
Tobias Grieger
dad8208a4d raft: avoid panics during *node tests
`StartNode` runs a naked goroutine, so it's impossible to test against
it in a way that will reliably produce contained test failures when
assertions are hit on the `(*node).run` goroutine.

This commit introduces a harness that we can use in tests to wrap
this goroutine and allow it to defer errors to `*testing.T`.

Note that tests of `Node` still need to be architected carefully
since it's easy to produce a deadlock in them should things not
go exactly as planned.

Signed-off-by: Tobias Grieger <tobias.b.grieger@gmail.com>
2022-09-20 08:59:37 +02:00
Tobias Grieger
169f4c3cc7 raft: don't emit unstable CommittedEntries
See https://github.com/etcd-io/etcd/issues/14370.

When run in a single-voter configuration, prior to this PR
raft would emit `HardState`s that would emit a proposed `Entry`
simultaneously in `CommittedEntries` and `Entries`.

To be correct, this requires users of the raft library to enforce an
ordering between appending to the log and notifying the client about
`CommittedEntries` also present in `Entries`. This was easy to miss.

Walk back this behavior to arrive at a simpler contract: what's
emitted in `CommittedEntries` is truly committed, i.e. present
in stable storage on a quorum of voters.

This in turn pessimizes the single-voter case: rather than fully
handling an `Entry` in just one `Ready`, now two are required,
and in particular one has to do extra work to save on allocations.

We accept this as a good tradeoff, since raft primarily serves
multi-voter configurations.

Signed-off-by: Tobias Grieger <tobias.b.grieger@gmail.com>
2022-09-20 08:59:37 +02:00