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

storage: delete ReplicatedEvalResult.BlockReads #43048

Merged

Conversation

nvanbenschoten
Copy link
Member

@nvanbenschoten nvanbenschoten commented Dec 8, 2019

Closes #32583.

This series of commits phases out and deleted ReplicatedEvalResult.BlockReads. In doing so, it addresses the remainder of #32583.

Most of the effort here was in digging through the history of BlockReads and convincing myself that these changes were sufficient to address the synchronization concerns that led to its creation. The individual commit messages do their best to explore this archaeology. Once that was complete, the rest of the change was straightforward.

This is about four cleanups deep in a chain of refactoring that's clearing the way for the new concurrency package, so I'm hoping to push this through over the next few days.

@cockroach-teamcity
Copy link
Member

This change is Reviewable

Copy link
Member

@tbg tbg left a comment

Choose a reason for hiding this comment

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

Everything LGTM except the remove of readOnlyCmdMu, where I share your concerns and also your suspicion that today's code isn't correct.

Could the latch manager help? If before destruction we "poison" the latch mgr (i.e. let it "refuse" new latches) and atomically push through a latch that covers everything (i.e. flush out any pending requests), we should be good to go, right? Maybe this is a decent stand-in for decent replica lifecycle management.

Reviewed 2 of 2 files at r1, 1 of 1 files at r2, 4 of 4 files at r3, 4 of 4 files at r4, 4 of 4 files at r5.
Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @andreimatei, @irfansharif, and @nvanbenschoten)


pkg/storage/replica_application_state_machine.go, line 984 at r4 (raw file):

		defer unlock()
	}
	if cmd.replicatedResult().BlockReads {

Add something to the commit message on why it's safe to remove this without a migration: even though replicated, it really only ever mattered on the proposer node (i.e. it never needed to be replicated in the first place).

@nvanbenschoten nvanbenschoten changed the title storage: delete ReplicatedEvalResult.BlockReads and Replica.readOnlyCmdMu storage: delete ReplicatedEvalResult.BlockReads Dec 12, 2019
Copy link
Member Author

@nvanbenschoten nvanbenschoten left a comment

Choose a reason for hiding this comment

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

where I share your concerns and also your suspicion that today's code isn't correct.

Yeah, this is pretty troubling. I don't think it will be too hard to confirm or disprove. I'll take a shot at doing so.

Could the latch manager help? If before destruction we "poison" the latch mgr (i.e. let it "refuse" new latches) and atomically push through a latch that covers everything (i.e. flush out any pending requests), we should be good to go, right? Maybe this is a decent stand-in for decent replica lifecycle management.

I think you're on to something here. I would love it if we could use the latch mgr as the single synchronization primitive for a replica and not have other random locking. My concern would just be that it's not re-entrant and there might be cases where we would need it to be.

I'll continue trying to kill off the readOnlyCmdMu, but I'm going to pull that commit for now so that I can push the rest of this through since it's blocking some other cleanup.

bors r+

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @andreimatei, @irfansharif, and @tbg)


pkg/storage/replica_application_state_machine.go, line 984 at r4 (raw file):

Previously, tbg (Tobias Grieger) wrote…

Add something to the commit message on why it's safe to remove this without a migration: even though replicated, it really only ever mattered on the proposer node (i.e. it never needed to be replicated in the first place).

Done.

@craig
Copy link
Contributor

craig bot commented Dec 12, 2019

Merge conflict

The decision to block reads on lease transfers has a long history. All lease
changes began blocking reads in 2896b8c. This was later reduced to just lease
transfers (not extensions) in 231089c. The reason for blocking reads on lease
transfers was that "if we didn't block concurrent reads, there'd be a chance
that reads could sneak in on a new lease holder between setting the lease and
updating the low water mark [of the timestamp cache]."

As the corresponding TODO mentions, it's not clear that this would actually
cause any issues. It's actually much more likely that it would cause issues
for writes, which actually consult the timestamp cache. However, none of this
is a concern in practice because `Replica.leasePostApply` updates the timestamp
cache before updating the Replica's lease, so such a race is not possible.
This has been the case since c54d9b0.

This commit addresses the TODO and stops blocking reads on lease transfers.

Release note: None
This commit stops using the BlockReads flag to block reads during the
application of a MergeTrigger. There was no need to block reads during
this time. Reads to the RHS of the range will be rejected up until the
call to Replica.setDesc in Store.MergeRange, at which point they will
be accepted without issue.

The use of BlockReads here dates back to 2896b8c, where it was added in
with a reference to cockroachdb#3148 (fixed by 34b2037). The referenced issue has
to do with splits and not merges. However, the call to BlockReads was
carried over to both the SplitTrigger and MergeTrigger accidentally when
the single EndTransaction CommitTrigger handler was split in 2896b8c.

Release note: None
Fixes cockroachdb#32583.

This commit uses non-MVCC latches introduced in cockroachdb#39765 to properly synchronize
reads to the RHS of a split and the split itself. Specifically, this addresses
the concern cockroachdb#32583 about reads below the split timestamp being able to read from
the the RHS of the split even after the RHS is governed by a new timestamp cache
(cockroachdb#3148) and even after it has allowed that data to be rebalanced away.

These concerns had previously been addressed by using the BlockReads flag and
synchronizing with reads through the readOnlyCmdMu. Now that latching gives
us what we need, we can stop setting the BlockReads flag on the SplitTrigger.

Release note (performance improvement): Range splits are now less disruptive
to foreground reads.
Now that it's not used for lease transfers, merges, or splits, it's no
longer used at all.

The field is safe to get rid of (ignore) without a migration, even though
it is replicated, because it only ever mattered on the proposer node. In
other words, it never needed to be replicated in the first place.

Release note: None
We can't quite remove the readOnlyCmdMu because of concerns with replica
destruction (see PR discussion). However, the prior cleanup allows us to
remove the awkward requirements around how the readOnlyCmdMu interacted
with the timestamp cache and needed to interleave its locking with the
latch manager.

This enabled further cleanup.

Release note: None
@nvanbenschoten
Copy link
Member Author

bors r+

craig bot pushed a commit that referenced this pull request Dec 12, 2019
43048: storage: delete ReplicatedEvalResult.BlockReads r=nvanbenschoten a=nvanbenschoten

Closes #32583.

This series of commits phases out and deleted `ReplicatedEvalResult.BlockReads`. In doing so, it addresses the remainder of #32583.

Most of the effort here was in digging through the history of BlockReads and convincing myself that these changes were sufficient to address the synchronization concerns that led to its creation. The individual commit messages do their best to explore this archaeology. Once that was complete, the rest of the change was straightforward.

This is about four cleanups deep in a chain of refactoring that's clearing the way for the new `concurrency` package, so I'm hoping to push this through over the next few days.

Co-authored-by: Nathan VanBenschoten <nvanbenschoten@gmail.com>
@craig
Copy link
Contributor

craig bot commented Dec 12, 2019

Build succeeded

@craig craig bot merged commit 645982e into cockroachdb:master Dec 12, 2019
@nvanbenschoten nvanbenschoten deleted the nvanbenschoten/removeBlockReads branch December 27, 2019 22:59
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.

storage: acquire read latches instead of write latches during range splits
3 participants