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

raftlog: correctly decode empty commands #100401

Merged
merged 1 commit into from
Apr 4, 2023

Conversation

erikgrinaker
Copy link
Contributor

@erikgrinaker erikgrinaker commented Apr 1, 2023

When unquiescing a Raft group, an empty command is proposed to wake the Raft leader. During application, empty entries are considered noops, but only if they don't have a command ID. However, Raft entry decoding would preserve the command ID of an empty payload. CheckForcedErr() thus no longer considered this a noop, instead returning an error because the ProposerLeaseSequence of 0 was older than the current lease. Construction and processing of this error had a non-negligible cost when unquiescing a large number of ranges.

This patch makes sure such empty commands are decoded as empty entries, without a command ID, and thus considered noops.

Resolves #100400.

Epic: none
Release note: None

@erikgrinaker erikgrinaker added the backport-23.1.x Flags PRs that need to be backported to 23.1 label Apr 1, 2023
@erikgrinaker erikgrinaker requested review from pav-kv and tbg April 1, 2023 16:58
@erikgrinaker erikgrinaker requested a review from a team as a code owner April 1, 2023 16:58
@erikgrinaker erikgrinaker self-assigned this Apr 1, 2023
@erikgrinaker erikgrinaker requested a review from a team April 1, 2023 16:58
@blathers-crl
Copy link

blathers-crl bot commented Apr 1, 2023

It looks like your PR touches production code but doesn't add or edit any test code. Did you consider adding tests to your PR?

🦉 Hoot! I am a Blathers, a bot for CockroachDB. My owner is dev-inf.

@cockroach-teamcity
Copy link
Member

This change is Reviewable

@erikgrinaker
Copy link
Contributor Author

erikgrinaker commented Apr 1, 2023

An alternative here is for either Entry.load() or CheckForcedErr() to handle empty payloads as a noop. I don't have a strong opinion either way -- it would buy us a command ID, which would allow us to disambiguate these from the empty proposals that Raft itself submits, at the cost of a few additional bytes, but otherwise I don' t think we really care.

@erikgrinaker erikgrinaker force-pushed the unquiesce-empty-entry branch from 51efa85 to c4d50c9 Compare April 1, 2023 17:00
@erikgrinaker
Copy link
Contributor Author

Note to self: check for any backwards compatibility concerns with 22.2 here.

@erikgrinaker erikgrinaker force-pushed the unquiesce-empty-entry branch from c4d50c9 to d6bbe6b Compare April 2, 2023 17:31
@erikgrinaker
Copy link
Contributor Author

v22.2 uses an empty payload rather than an empty entry:

data := kvserverbase.EncodeRaftCommand(kvserverbase.RaftVersionStandard, makeIDKey(), nil)
_ = r.mu.internalRaftGroup.Propose(data)

This empty payload was handled here:

d.idKey, encodedCommand = kvserverbase.DecodeRaftCommand(e.Data)
// An empty command is used to unquiesce a range and wake the
// leader. Clear commandID so it's ignored for processing.
if len(encodedCommand) == 0 {
d.idKey = ""
} else if err := protoutil.Unmarshal(encodedCommand, &d.raftCmd); err != nil {
return wrapWithNonDeterministicFailure(err, "while unmarshaling entry")
}

I've therefore updated this PR to retain the previous encoding (with command ID), and instead decode empty payloads into empty entries, for backwards compatibility with 22.2 entries.

@erikgrinaker erikgrinaker force-pushed the unquiesce-empty-entry branch from d6bbe6b to d50a5c0 Compare April 2, 2023 17:33
@erikgrinaker erikgrinaker changed the title kvserver: propose empty entry on unquiescence raftlog: correctly decode empty commands Apr 2, 2023
@erikgrinaker erikgrinaker force-pushed the unquiesce-empty-entry branch from d50a5c0 to ef559b6 Compare April 4, 2023 11:03
Copy link
Collaborator

@pav-kv pav-kv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ended up nits-only, so feel free to skip them.

pkg/kv/kvserver/kvserverbase/forced_error.go Outdated Show resolved Hide resolved
pkg/kv/kvserver/raftlog/entry_test.go Outdated Show resolved Hide resolved
pkg/kv/kvserver/raftlog/entry.go Outdated Show resolved Hide resolved
@pav-kv
Copy link
Collaborator

pav-kv commented Apr 4, 2023

An alternative here is for either Entry.load() or CheckForcedErr() to handle empty payloads as a noop. I don't have a strong opinion either way -- it would buy us a command ID, which would allow us to disambiguate these from the empty proposals that Raft itself submits, at the cost of a few additional bytes, but otherwise I don' t think we really care.

Maybe all of these would be better indicated with some explicit enum, but it would be a bigger change.

When unquiescing a Raft group, an empty command is proposed to wake the
Raft leader. During application, empty entries are considered noops, but
only if they don't have a command ID. However, Raft entry decoding would
preserve the command ID of an empty payload. `CheckForcedErr()` thus no
longer considered this a noop, instead returning an error because the
`ProposerLeaseSequence` of 0 was older than the current lease.
Construction and processing of this error had a non-negligible cost when
unquiescing a large number of ranges.

This patch makes sure such empty commands are decoded as empty entries,
without a command ID, and thus considered noops.

Epic: none
Release note: None
@erikgrinaker erikgrinaker force-pushed the unquiesce-empty-entry branch from ef559b6 to 904afdd Compare April 4, 2023 15:57
@erikgrinaker
Copy link
Contributor Author

Maybe all of these would be better indicated with some explicit enum, but it would be a bigger change.

Yeah, I'm going for a targeted change here, since this needs a 23.1 backport.

@erikgrinaker
Copy link
Contributor Author

TFTR!

bors r+

@craig
Copy link
Contributor

craig bot commented Apr 4, 2023

Build succeeded:

@craig craig bot merged commit c71b0ed into cockroachdb:master Apr 4, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport-23.1.x Flags PRs that need to be backported to 23.1
Projects
None yet
Development

Successfully merging this pull request may close these issues.

kvserver: unquiesce proposal always errors
3 participants