Skip to content

kv: avoid thrashing and livelocking on multiple concurrent Range merge txns#59026

Merged
craig[bot] merged 1 commit intocockroachdb:masterfrom
nvb:nvanbenschoten/mergeLock2
Feb 1, 2021
Merged

kv: avoid thrashing and livelocking on multiple concurrent Range merge txns#59026
craig[bot] merged 1 commit intocockroachdb:masterfrom
nvb:nvanbenschoten/mergeLock2

Conversation

@nvb
Copy link
Copy Markdown
Contributor

@nvb nvb commented Jan 15, 2021

Fixes #46639.

This commit updates the Range merge transaction to perform a locking read on the left-hand side's range descriptor. Locking the descriptor early (i.e. on the read instead of the write of the read-modify-write operation) helps prevent multiple concurrent Range merges from thrashing. Thrashing is especially detrimental for Range merges because any restart results in an abort, so thrashing can result in indefinite livelock.

Before this change, I was easily able to reproduce the livelock discussed in #46639 by stressing TestKVNemesisMultiNode with the merge probability increased by 10x. When stressing on a 20 node roachprod cluster and using a 60s timeout, the test would typically fail after about 6,000 iterations. With this change and under the same setup, I have yet to see the failure over 125,000 iterations.

@nvb nvb requested a review from andreimatei January 15, 2021 00:57
@cockroach-teamcity
Copy link
Copy Markdown
Member

This change is Reviewable

@nvb nvb force-pushed the nvanbenschoten/mergeLock2 branch from 48d6ac3 to 646f0d2 Compare January 15, 2021 03:52
@nvb nvb requested review from aayushshah15 and removed request for andreimatei January 26, 2021 17:58
@nvb nvb force-pushed the nvanbenschoten/mergeLock2 branch from 646f0d2 to cc05807 Compare January 27, 2021 01:02
Copy link
Copy Markdown
Contributor

@aayushshah15 aayushshah15 left a comment

Choose a reason for hiding this comment

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

:lgtm: thanks for updating the tech-note along with the change! I know this is blocked on the other PR, I'll get to that ASAP.

Reviewed 1 of 3 files at r3.
Reviewable status: :shipit: complete! 1 of 0 LGTMs obtained (waiting on @nvanbenschoten)


docs/tech-notes/range-merges.md, line 252 at r3 (raw file):

As of v21.1, the merge transaction uses a locking read on the LHS range's
transaction record as its first course of action. This eliminates thrashing and
livelock in the face of concurrent merge attempts. It also has the effect of

Do you think it's worth pointing out that we only expect these concurrent merge attempts in testing scenarios (right?)


pkg/kv/kvserver/replica_command.go, line 2273 at r3 (raw file):

// The method allows callers to specify whether a locking read should be used or
// not. A locking read can be used to manage contention and avoid transaction
// restarts in a read-modify-write operation (which all users of this method

Do you think the part in parenthesis could easily rot? If not, we could consider making this method always issue locking gets and remove the forUpdate option.

…e txns

Fixes cockroachdb#46639.

This commit updates the Range merge transaction to perform a locking read on
the left-hand side's range descriptor. Locking the descriptor early (i.e. on
the read instead of the write of the read-modify-write operation) helps
prevent multiple concurrent Range merges from thrashing. Thrashing is
especially detrimental for Range merges because any restart results in an
abort, so thrashing can result in indefinite livelock.

Before this change, I was easily able to reproduce the livelock discussed
in cockroachdb#46639 by stressing `TestKVNemesisMultiNode` with the merge probability
increased by 10x. When stressing on a 20 node roachprod cluster and using a
60s timeout, the test would typically fail after about 6,000 iterations.
With this change and under the same setup, I have yet to see the failure
over 125,000 iterations.
@nvb nvb force-pushed the nvanbenschoten/mergeLock2 branch from cc05807 to c3f328e Compare January 31, 2021 23:44
Copy link
Copy Markdown
Contributor Author

@nvb nvb left a comment

Choose a reason for hiding this comment

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

TFTR!

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (and 1 stale) (waiting on @aayushshah15)


docs/tech-notes/range-merges.md, line 252 at r3 (raw file):

Previously, aayushshah15 (Aayush Shah) wrote…

Do you think it's worth pointing out that we only expect these concurrent merge attempts in testing scenarios (right?)

Done.


pkg/kv/kvserver/replica_command.go, line 2273 at r3 (raw file):

Do you think the part in parenthesis could easily rot?

This is a pretty specialized function, so I don't imagine it being used for other things.

If not, we could consider making this method always issue locking gets and remove the forUpdate option.

That's a good question. I actually had this written without the forUpdate option at first, but I decided not to change the behavior of all transactions that use it at the same time, especially when we're in the migration period where the recipient might not even respect the locking field in the GetRequest. I do think we will eventually want to switch over to that, though. I added a TODO.

@nvb
Copy link
Copy Markdown
Contributor Author

nvb commented Feb 1, 2021

bors r+

@craig
Copy link
Copy Markdown
Contributor

craig bot commented Feb 1, 2021

Build succeeded:

@craig craig bot merged commit d62f71d into cockroachdb:master Feb 1, 2021
@nvb nvb deleted the nvanbenschoten/mergeLock2 branch February 1, 2021 03:13
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

Successfully merging this pull request may close these issues.

kv: kvnemesis can thrash and livelock on multiple concurrent Range merges

3 participants