diff options
author | Randolph Tan <randolph@10gen.com> | 2015-01-06 14:22:58 -0500 |
---|---|---|
committer | Randolph Tan <randolph@10gen.com> | 2015-01-06 17:42:48 -0500 |
commit | 293bf1caf51df5b9cf7c882f2e6312769e1716a2 (patch) | |
tree | c31bfee5f41ff3c93558b2e097a7c277ffdfc7ac | |
parent | 4b7a350224eef7676b4c49e2616bc2bee347420f (diff) | |
download | mongo-293bf1caf51df5b9cf7c882f2e6312769e1716a2.tar.gz |
SERVER-16683 Decrease mongos memory footprint when shards have several tags
-rw-r--r-- | src/mongo/s/balance.cpp | 20 | ||||
-rw-r--r-- | src/mongo/s/balancer_policy.cpp | 126 | ||||
-rw-r--r-- | src/mongo/s/balancer_policy.h | 5 | ||||
-rw-r--r-- | src/mongo/s/chunk.cpp | 19 | ||||
-rw-r--r-- | src/mongo/s/shard.cpp | 7 | ||||
-rw-r--r-- | src/mongo/s/shard.h | 7 | ||||
-rw-r--r-- | src/mongo/s/type_shard.cpp | 4 |
7 files changed, 137 insertions, 51 deletions
diff --git a/src/mongo/s/balance.cpp b/src/mongo/s/balance.cpp index d89c64912fe..d0b892a3464 100644 --- a/src/mongo/s/balance.cpp +++ b/src/mongo/s/balance.cpp @@ -252,15 +252,18 @@ namespace mongo { // TODO: skip unresponsive shards and mark information as stale. // - vector<Shard> allShards; - Shard::getAllShards( allShards ); - if ( allShards.size() < 2) { + ShardInfoMap shardInfo; + Status loadStatus = DistributionStatus::populateShardInfoMap(&shardInfo); + + if (!loadStatus.isOK()) { + warning() << "failed to load shard metadata" << causedBy(loadStatus) << endl; + return; + } + + if (shardInfo.size() < 2) { LOG(1) << "can't balance without more active shards" << endl; return; } - - ShardInfoMap shardInfo; - DistributionStatus::populateShardInfoMap(allShards, &shardInfo); OCCASIONALLY warnOnMultiVersion( shardInfo ); @@ -305,11 +308,10 @@ namespace mongo { continue; } - for ( vector<Shard>::iterator i=allShards.begin(); i!=allShards.end(); ++i ) { + for (ShardInfoMap::const_iterator i = shardInfo.begin(); i != shardInfo.end(); ++i) { // this just makes sure there is an entry in shardToChunksMap for every shard - Shard s = *i; OwnedPointerVector<ChunkType>*& chunkList = - shardToChunksMap.mutableMap()[s.getName()]; + shardToChunksMap.mutableMap()[i->first]; if (chunkList == NULL) { chunkList = new OwnedPointerVector<ChunkType>(); diff --git a/src/mongo/s/balancer_policy.cpp b/src/mongo/s/balancer_policy.cpp index 207de2b6680..2b1faa88006 100644 --- a/src/mongo/s/balancer_policy.cpp +++ b/src/mongo/s/balancer_policy.cpp @@ -34,6 +34,7 @@ #include "mongo/s/balancer_policy.h" #include "mongo/s/chunk.h" #include "mongo/s/config.h" +#include "mongo/s/type_shard.h" #include "mongo/s/type_tags.h" #include "mongo/util/log.h" #include "mongo/util/stringutils.h" @@ -42,6 +43,52 @@ namespace mongo { + namespace { + + Status extractShardInfo(const std::string& shardHost, + std::string* version, + bool* hasOpsQueued, + long long* mappedMB) { + BSONObj serverStatus; + + try { + ScopedDbConnection conn(shardHost); + + bool ok = conn->runCommand("admin", BSON("serverStatus" << 1), serverStatus); + conn.done(); + + uassert(28598, + str::stream() << "call to serverStatus on " << shardHost + << " failed: " << serverStatus, + ok); + } + catch (const DBException& ex) { + return ex.toStatus(); + } + + BSONElement versionElement = serverStatus["version"]; + if (versionElement.type() != String) { + return Status(ErrorCodes::UnsupportedFormat, + "supports only string type for version field in serverStatus"); + } + + *version = serverStatus["version"].String(); + + *hasOpsQueued = serverStatus["writeBacksQueued"].booleanSafe(); + + BSONElement memMappedElement = serverStatus.getFieldDotted("mem.mapped"); + + if (!memMappedElement.isNumber()) { + return Status(ErrorCodes::UnsupportedFormat, + "supports only numeric type for mem.mapped field in serverStatus"); + } + + *mappedMB = memMappedElement.numberLong(); + + return Status::OK(); + } + } + string TagRange::toString() const { return str::stream() << min << " -->> " << max << " on " << tag; } @@ -241,31 +288,78 @@ namespace mongo { } } - void DistributionStatus::populateShardInfoMap(const vector<Shard> allShards, - ShardInfoMap* shardInfo) { - for (vector<Shard>::const_iterator it = allShards.begin(); - it != allShards.end(); ++it ) { - const Shard& shard = *it; - ShardStatus status = shard.getStatus(); - shardInfo->insert(make_pair(shard.getName(), - ShardInfo(shard.getMaxSize(), - status.mapped(), - shard.isDraining(), - status.hasOpsQueued(), - shard.tags(), - status.mongoVersion()))); + Status DistributionStatus::populateShardInfoMap(ShardInfoMap* shardInfo) { + try { + ScopedDbConnection conn(configServer.getPrimary().getConnString(), 30); + + auto_ptr<DBClientCursor> cursor(conn->query(ShardType::ConfigNS , Query())); + uassert(28597, "Failed to load shard config", cursor.get() != NULL); + + while (cursor->more()) { + ShardType shard; + std::string errMsg; + bool parseOk = shard.parseBSON(cursor->next(), &errMsg); + + if (!parseOk) { + return Status(ErrorCodes::UnsupportedFormat, + errMsg); + } + + std::string mongoShardVersion; + bool hasWriteBacksQueued = false; + long long mMappedMB = 0; + Status shardStatus = extractShardInfo(shard.getHost(), + &mongoShardVersion, + &hasWriteBacksQueued, + &mMappedMB); + + if (!shardStatus.isOK()) { + return shardStatus; + } + + std::set<std::string> dummy; + ShardInfo newShardEntry(shard.getMaxSize(), + mMappedMB, + shard.getDraining(), + hasWriteBacksQueued, + dummy, + mongoShardVersion); + + if (shard.isTagsSet()) { + BSONArrayIteratorSorted tagIter(shard.getTags()); + while (tagIter.more()) { + BSONElement tagElement = tagIter.next(); + if (tagElement.type() != String) { + return Status(ErrorCodes::UnsupportedFormat, + str::stream() << "shard tags only supports strings, " + << "found " << typeName(tagElement.type())); + } + + newShardEntry.addTag(tagElement.String()); + } + } + + shardInfo->insert(make_pair(shard.getName(), newShardEntry)); + } + + conn.done(); } + catch (const DBException& ex) { + return ex.toStatus(); + } + + return Status::OK(); } - void DistributionStatus::populateShardToChunksMap(const vector<Shard>& allShards, + void DistributionStatus::populateShardToChunksMap(const ShardInfoMap& allShards, const ChunkManager& chunkMgr, ShardToChunksMap* shardToChunksMap) { // Makes sure there is an entry in shardToChunksMap for every shard. - for (vector<Shard>::const_iterator it = allShards.begin(); + for (ShardInfoMap::const_iterator it = allShards.begin(); it != allShards.end(); ++it) { OwnedPointerVector<ChunkType>*& chunkList = - (*shardToChunksMap)[it->getName()]; + (*shardToChunksMap)[it->first]; if (chunkList == NULL) { chunkList = new OwnedPointerVector<ChunkType>(); diff --git a/src/mongo/s/balancer_policy.h b/src/mongo/s/balancer_policy.h index 1ef9b83a18f..b1ea918811e 100644 --- a/src/mongo/s/balancer_policy.h +++ b/src/mongo/s/balancer_policy.h @@ -187,13 +187,12 @@ namespace mongo { /** writes all state to log() */ void dump() const; - static void populateShardInfoMap(const std::vector<Shard> allShards, - ShardInfoMap* shardInfo); + static Status populateShardInfoMap(ShardInfoMap* shardInfo); /** * Note: jumbo and versions are not set. */ - static void populateShardToChunksMap(const std::vector<Shard>& allShards, + static void populateShardToChunksMap(const ShardInfoMap& allShards, const ChunkManager& chunkMgr, ShardToChunksMap* shardToChunksMap); diff --git a/src/mongo/s/chunk.cpp b/src/mongo/s/chunk.cpp index d8809b22406..4a8a63c8d58 100644 --- a/src/mongo/s/chunk.cpp +++ b/src/mongo/s/chunk.cpp @@ -81,21 +81,24 @@ namespace mongo { */ static bool tryMoveToOtherShard(const ChunkManager& manager, const ChunkType& chunk) { // reload sharding metadata before starting migration - Shard::reloadShardInfo(); ChunkManagerPtr chunkMgr = manager.reload(false /* just reloaded in mulitsplit */); - vector<Shard> allShards; - Shard::getAllShards(allShards); - if (allShards.size() < 2) { - LOG(0) << "no need to move top chunk since there's only 1 shard" << endl; + ShardInfoMap shardInfo; + Status loadStatus = DistributionStatus::populateShardInfoMap(&shardInfo); + + if (!loadStatus.isOK()) { + warning() << "failed to load shard metadata while trying to moveChunk after " + << "auto-splitting" << causedBy(loadStatus); return false; } - ShardInfoMap shardInfo; - DistributionStatus::populateShardInfoMap(allShards, &shardInfo); + if (shardInfo.size() < 2) { + LOG(0) << "no need to move top chunk since there's only 1 shard" << endl; + return false; + } OwnedPointerMap<string, OwnedPointerVector<ChunkType> > shardToChunkMap; - DistributionStatus::populateShardToChunksMap(allShards, + DistributionStatus::populateShardToChunksMap(shardInfo, *chunkMgr, &shardToChunkMap.mutableMap()); diff --git a/src/mongo/s/shard.cpp b/src/mongo/s/shard.cpp index 1e35361381f..783fea8becf 100644 --- a/src/mongo/s/shard.cpp +++ b/src/mongo/s/shard.cpp @@ -132,13 +132,6 @@ namespace mongo { ShardPtr s( new Shard( name , host , maxSize , isDraining ) ); - if ( o[ ShardType::tags() ].type() == Array ) { - vector<BSONElement> v = o[ ShardType::tags() ].Array(); - for ( unsigned j=0; j<v.size(); j++ ) { - s->addTag( v[j].String() ); - } - } - _lookup[name] = s; _installHost( host , s ); } diff --git a/src/mongo/s/shard.h b/src/mongo/s/shard.h index 81b7952ada9..247fbde5bdc 100644 --- a/src/mongo/s/shard.h +++ b/src/mongo/s/shard.h @@ -60,8 +60,7 @@ namespace mongo { Shard( const Shard& other ) : _name( other._name ) , _addr( other._addr ) , _cs( other._cs ) , - _maxSize( other._maxSize ) , _isDraining( other._isDraining ), - _tags( other._tags ) { + _maxSize( other._maxSize ) , _isDraining( other._isDraining ) { } Shard( const Shard* other ) @@ -151,9 +150,6 @@ namespace mongo { */ bool containsNode( const string& node ) const; - const set<string>& tags() const { return _tags; } - void addTag( const string& tag ) { _tags.insert( tag ); } - static void getAllShards( vector<Shard>& all ); static void printShardInfo( ostream& out ); static Shard lookupRSName( const string& name); @@ -181,7 +177,6 @@ namespace mongo { ConnectionString _cs; long long _maxSize; // in MBytes, 0 is unlimited bool _isDraining; // shard is currently being removed - set<string> _tags; }; typedef shared_ptr<Shard> ShardPtr; diff --git a/src/mongo/s/type_shard.cpp b/src/mongo/s/type_shard.cpp index bf24b19b86a..2b9a4012696 100644 --- a/src/mongo/s/type_shard.cpp +++ b/src/mongo/s/type_shard.cpp @@ -38,8 +38,8 @@ namespace mongo { const BSONField<std::string> ShardType::name("_id"); const BSONField<std::string> ShardType::host("host"); - const BSONField<bool> ShardType::draining("draining"); - const BSONField<long long> ShardType::maxSize("maxSize"); + const BSONField<bool> ShardType::draining("draining", false); + const BSONField<long long> ShardType::maxSize("maxSize", 0); const BSONField<BSONArray> ShardType::tags("tags"); ShardType::ShardType() { |