From b483650696b6d67dd3c651b3e8cd2926d3776ff3 Mon Sep 17 00:00:00 2001 From: Amirsaman Memaripour Date: Fri, 3 Apr 2020 19:05:31 -0400 Subject: SERVER-46514 Normalize host selection for mirrored reads --- src/mongo/db/mirror_maestro.cpp | 64 ++++++++++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 13 deletions(-) (limited to 'src/mongo/db/mirror_maestro.cpp') diff --git a/src/mongo/db/mirror_maestro.cpp b/src/mongo/db/mirror_maestro.cpp index 7f898db664d..ea604566f0d 100644 --- a/src/mongo/db/mirror_maestro.cpp +++ b/src/mongo/db/mirror_maestro.cpp @@ -34,6 +34,8 @@ #include "mongo/db/mirror_maestro.h" +#include +#include #include #include @@ -71,6 +73,7 @@ constexpr auto kMirroredReadsName = "mirroredReads"_sd; constexpr auto kMirroredReadsSeenKey = "seen"_sd; constexpr auto kMirroredReadsSentKey = "sent"_sd; constexpr auto kMirroredReadsResolvedKey = "resolved"_sd; +constexpr auto kMirroredReadsResolvedBreakdownKey = "resolvedBreakdown"_sd; MONGO_FAIL_POINT_DEFINE(mirrorMaestroExpectsResponse); @@ -182,11 +185,46 @@ public: if (MONGO_unlikely(mirrorMaestroExpectsResponse.shouldFail())) { // We only can see if the command resolved if we got a response section.append(kMirroredReadsResolvedKey, resolved.loadRelaxed()); + section.append(kMirroredReadsResolvedBreakdownKey, resolvedBreakdown.toBSON()); } return section.obj(); }; + /** + * Maintains a breakdown for resolved requests by host name. + * This class may only be used for testing (e.g., as part of a fail-point). + */ + class ResolvedBreakdownByHost { + public: + void onResponseReceived(const HostAndPort& host) noexcept { + const auto hostName = host.toString(); + stdx::lock_guard lk(_mutex); + + if (_resolved.find(hostName) == _resolved.end()) { + _resolved[hostName] = 0; + } + + _resolved[hostName]++; + } + + BSONObj toBSON() const noexcept { + stdx::lock_guard lk(_mutex); + BSONObjBuilder bob; + for (auto entry : _resolved) { + bob.append(entry.first, entry.second); + } + return bob.obj(); + } + + private: + mutable Mutex _mutex = MONGO_MAKE_LATCH("ResolvedBreakdownByHost"_sd); + + stdx::unordered_map _resolved; + }; + + ResolvedBreakdownByHost resolvedBreakdown; + AtomicWord seen; AtomicWord sent; AtomicWord resolved; @@ -266,24 +304,20 @@ void MirrorMaestroImpl::tryMirror(std::shared_ptr invocation) gMirroredReadsSection.seen.fetchAndAdd(1); auto params = _params->_data.get(); - auto samplingParams = MirroringSampler::SamplingParameters(params.getSamplingRate()); - if (!_sampler.shouldSample(samplingParams)) { - // If we wouldn't select a host, then nothing more to do + if (params.getSamplingRate() == 0) { + // Nothing to do if sampling rate is zero. return; } auto imr = _topologyVersionObserver.getCached(); - if (!imr) { - // If we don't have an IsMasterResponse, we can't know where to send our mirrored - // request + auto samplingParams = MirroringSampler::SamplingParameters(params.getSamplingRate()); + if (!_sampler.shouldSample(imr, samplingParams)) { + // If we wouldn't select a host, then nothing more to do return; } auto hosts = _sampler.getRawMirroringTargets(imr); - if (hosts.empty()) { - // If we had no eligible hosts, nothing more to do - return; - } + invariant(!hosts.empty()); auto clientExecutor = ClientOutOfLineExecutor::get(Client::getCurrent()); auto clientExecutorHandle = clientExecutor->getHandle(); @@ -333,9 +367,12 @@ void MirrorMaestroImpl::_mirror(const std::vector& hosts, return bob.obj(); }(); - // TODO SERVER-46514 When we figure out how to deallocate CommandInvocations effectively, we - // should do a normalized sample here. - for (auto& host : hosts) { + // Mirror to a normalized subset of eligible hosts (i.e., secondaries). + const auto startIndex = rand() % hosts.size(); + const auto mirroringFactor = std::ceil(params.getSamplingRate() * hosts.size()); + + for (auto i = 0; i < mirroringFactor; i++) { + auto& host = hosts[(startIndex + i) % hosts.size()]; auto mirrorResponseCallback = [host](auto& args) { if (MONGO_likely(!mirrorMaestroExpectsResponse.shouldFail())) { // If we don't expect responses, then there is nothing to do here @@ -349,6 +386,7 @@ void MirrorMaestroImpl::_mirror(const std::vector& hosts, } gMirroredReadsSection.resolved.fetchAndAdd(1); + gMirroredReadsSection.resolvedBreakdown.onResponseReceived(host); LOGV2_DEBUG( 31457, 4, "Response received", "host"_attr = host, "response"_attr = args.response); }; -- cgit v1.2.1