Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
MB-54591: ActiveStream: Avoid lost wakeup due to race on itemsReady
+Summary+ There exists a race in ActiveStream between a notifying that a new mutation available, and processing the previous mutation(s). If the notification occurs just before ActiveStream sets a flag indicating that there's currently no more items to process, then the notification is lost and the DCP stream is not notified of this new mutation when it should be. This results in the DCP stream being behind by that seqno, until the the next mutation on the vBucket occurs with will re-notify the stream and cause it to process both. +Impact+ When it occurs, this bug introduces additional latency between a mutation occurring on the KV node, and it getting passed to the affected DCP client. For DCP connections which require a "current" set of seqnos to proceed - e.g. GSI when using request_plus queries, this can manifest as those operations hanging. Note the latency added is bounded by the mutation rate on the vBucket - the next mutation is guaranteed to wake up the stream (as it is now idle and there's no possible race). For workloads with moderate mutation rates (e.g. 1000 mutations per second per Bucket), the additional latency on average should be 1s. However for workloads with very low mutation rates (<100 per second) then on average the latency would be 10+ seconds. For workloads which are intermittent and idle for extended periods, the added latency could be large - as long as it takes for that vBucket to be modified again. +Details+ The race is between the itemsReady flag being tested in notifyStreamReady, and clearing itemsReady when there are no more items available for the stream in ActiveStream::next(). Flag is tested here: void ActiveStream::notifyStreamReady(bool force, DcpProducer* producer, uint64_t seqno) { bool inverse = false; if (force || itemsReady.compare_exchange_strong(inverse, true)) { if (seqno) { itemsReadySeqnosForNotify.lock()->push_back(seqno); } ... And it is set/reset here: std::unique_ptr<DcpResponse> ActiveStream::next(DcpProducer& producer) { std::unique_ptr<DcpResponse> response; switch (state_.load()) { ... case StreamState::InMemory: response = inMemoryPhase(producer); break; ... } itemsReady.store(response ? true : false); return response; } We can lose a notification (from ActiveStream::notifyStreamReady) from one front-end thread (performing a set) if the notification occurs while the DCP thread is executing ActiveStream::next() and has already called inMemoryPhase() and found the CheckpointManger empty - but *before* we clear itemsReady at the end of the function. To fix the lost wakeup we clear itemsReady _before_ we fetch the next response - and only set it back to true (inhibiting notifies) if we find we have at least one more item. This potentially swaps lost wakeups for unnecessary wakeups (i.e. if a notifyStreamReady() occurs in ActiveStream::next() between clearing itemsReady and re-setting it at the end) - but correctness > performance. Change-Id: I3ed9ff1abfe654b8ced4e9c8d084bd0ddaa668ee Reviewed-on: https://review.couchbase.org/c/kv_engine/+/182929 Well-Formed: Restriction Checker Reviewed-by: Ben Huddleston <ben.huddleston@couchbase.com> Tested-by: Build Bot <build@couchbase.com>
- Loading branch information
Showing
5 changed files
with
144 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters