diff options
author | Randolph Tan <randolph@10gen.com> | 2014-12-30 14:58:28 -0500 |
---|---|---|
committer | Randolph Tan <randolph@10gen.com> | 2015-01-06 13:10:17 -0500 |
commit | 9080534036974a91067cef0ace3aff60c65a123b (patch) | |
tree | bee444e65cfec2b845b304ae30e4060205740d77 /src | |
parent | f9bdad71e16409017df02058d2579cf659ef2e44 (diff) | |
download | mongo-9080534036974a91067cef0ace3aff60c65a123b.tar.gz |
SERVER-16683 Decrease mongos memory footprint when shards have several tags
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/dbtests/chunktests.cpp | 3 | ||||
-rw-r--r-- | src/mongo/dbtests/sharding.cpp | 3 | ||||
-rw-r--r-- | src/mongo/s/balance.cpp | 22 | ||||
-rw-r--r-- | src/mongo/s/balancer_policy.cpp | 68 | ||||
-rw-r--r-- | src/mongo/s/balancer_policy.h | 9 | ||||
-rw-r--r-- | src/mongo/s/chunk.cpp | 19 | ||||
-rw-r--r-- | src/mongo/s/cluster_client_internal.h | 3 | ||||
-rw-r--r-- | src/mongo/s/config.cpp | 3 | ||||
-rw-r--r-- | src/mongo/s/config.h | 3 | ||||
-rw-r--r-- | src/mongo/s/shard.cpp | 54 | ||||
-rw-r--r-- | src/mongo/s/shard.h | 27 | ||||
-rw-r--r-- | src/mongo/s/shard_test.cpp | 22 | ||||
-rw-r--r-- | src/mongo/s/type_shard.cpp | 4 |
13 files changed, 151 insertions, 89 deletions
diff --git a/src/mongo/dbtests/chunktests.cpp b/src/mongo/dbtests/chunktests.cpp index 7b86089185e..e9cb366f199 100644 --- a/src/mongo/dbtests/chunktests.cpp +++ b/src/mongo/dbtests/chunktests.cpp @@ -60,8 +60,7 @@ namespace mongo { Shard shard(name, name, 0 /* maxSize */, - false /* draining */, - BSONArray() /* tags */); + false /* draining */); shards.insert( shard ); ChunkPtr chunk( new Chunk( this, mySplitPoints[ i-1 ], mySplitPoints[ i ], diff --git a/src/mongo/dbtests/sharding.cpp b/src/mongo/dbtests/sharding.cpp index 505b34655d7..6a70c2b0a9c 100644 --- a/src/mongo/dbtests/sharding.cpp +++ b/src/mongo/dbtests/sharding.cpp @@ -110,8 +110,7 @@ namespace ShardingTests { _shard = Shard("shard0000", "$hostFooBar:27017", 0 /* maxSize */, - false /* draining */, - BSONArray() /* tags */); + false /* draining */); // Need to run this to ensure the shard is in the global lookup table Shard::installShard(_shard.getName(), _shard); diff --git a/src/mongo/s/balance.cpp b/src/mongo/s/balance.cpp index 6e61ecd58d0..6659c8e3f64 100644 --- a/src/mongo/s/balance.cpp +++ b/src/mongo/s/balance.cpp @@ -350,16 +350,19 @@ namespace mongo { // TODO: skip unresponsive shards and mark information as stale. // - vector<Shard> allShards; - Shard::getAllShards( allShards ); - if ( allShards.size() < 2) { - LOG(1) << "can't balance without more active shards" << endl; + ShardInfoMap shardInfo; + Status loadStatus = DistributionStatus::populateShardInfoMap(&shardInfo); + + if (!loadStatus.isOK()) { + warning() << "failed to load shard metadata" << causedBy(loadStatus); return; } - - ShardInfoMap shardInfo; - DistributionStatus::populateShardInfoMap(allShards, &shardInfo); + if (shardInfo.size() < 2) { + LOG(1) << "can't balance without more active shards"; + return; + } + OCCASIONALLY warnOnMultiVersion( shardInfo ); // @@ -403,11 +406,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 31596b107e8..58e0c32272a 100644 --- a/src/mongo/s/balancer_policy.cpp +++ b/src/mongo/s/balancer_policy.cpp @@ -36,12 +36,12 @@ #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" #include "mongo/util/text.h" - namespace mongo { string TagRange::toString() const { @@ -232,30 +232,66 @@ 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.getMaxSizeMB(), - status.dataSizeBytes() * 1024 * 1024, - shard.isDraining(), - 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::set<std::string> dummy; + ShardInfo newShardEntry(shard.getMaxSize(), + Shard::getShardDataSizeBytes(shard.getHost()) / + 1024 / 1024, + shard.getDraining(), + dummy, + Shard::getShardMongoVersion(shard.getHost())); + + 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 0d29d5956e2..2ae774f2fc7 100644 --- a/src/mongo/s/balancer_policy.h +++ b/src/mongo/s/balancer_policy.h @@ -184,13 +184,16 @@ namespace mongo { /** writes all state to log() */ void dump() const; - static void populateShardInfoMap(const std::vector<Shard> allShards, - ShardInfoMap* shardInfo); + /** + * Retrieves shard metadata information from the config server as well as some stats + * from the shards. + */ + 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 e50a6930dde..61a6769320f 100644 --- a/src/mongo/s/chunk.cpp +++ b/src/mongo/s/chunk.cpp @@ -100,21 +100,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/cluster_client_internal.h b/src/mongo/s/cluster_client_internal.h index 5bf4658cd19..12c2eccf50d 100644 --- a/src/mongo/s/cluster_client_internal.h +++ b/src/mongo/s/cluster_client_internal.h @@ -102,7 +102,8 @@ namespace mongo { // Helper function which throws on bad GLEs for non-SCC config servers void _checkGLE(ScopedDbConnection& conn); - // Helper function which throws for invalid cursor initialization + // Helper function which throws for invalid cursor initialization. + // Note: cursor ownership will be passed to this function. DBClientCursor* _safeCursor(std::auto_ptr<DBClientCursor> cursor); } diff --git a/src/mongo/s/config.cpp b/src/mongo/s/config.cpp index bf37bf9244c..9df7a847808 100644 --- a/src/mongo/s/config.cpp +++ b/src/mongo/s/config.cpp @@ -839,8 +839,7 @@ namespace mongo { _primary = Shard(_primary.getName(), ConnectionString(fullString, ConnectionString::SYNC), _primary.getMaxSizeMB(), - _primary.isDraining(), - _primary.tags()); + _primary.isDraining()); Shard::installShard(_primary.getName(), _primary); LOG(1) << " config string : " << fullString << endl; diff --git a/src/mongo/s/config.h b/src/mongo/s/config.h index 87e901a520e..4284ecf463e 100644 --- a/src/mongo/s/config.h +++ b/src/mongo/s/config.h @@ -108,8 +108,7 @@ namespace mongo { _primary("config", "", 0 /* maxSize */, - false /* draining */, - BSONArray() /* tags */), + false /* draining */), _shardingEnabled(false), _lock("DBConfig") , _hitConfigServerLock( "DBConfig::_hitConfigServerLock" ) { diff --git a/src/mongo/s/shard.cpp b/src/mongo/s/shard.cpp index f67fb4522f8..43bcb57c0a9 100644 --- a/src/mongo/s/shard.cpp +++ b/src/mongo/s/shard.cpp @@ -133,8 +133,7 @@ namespace mongo { ShardPtr shard = boost::make_shared<Shard>(shardData.getName(), shardData.getHost(), maxSize, - isDraining, - tags); + isDraining); _lookup[shardData.getName()] = shard; _installHost(shardData.getHost(), shard); @@ -352,32 +351,23 @@ namespace mongo { Shard::Shard(const std::string& name, const std::string& addr, long long maxSizeMB, - bool isDraining, - const BSONArray& tags): + bool isDraining): _name(name), _addr(addr), _maxSizeMB(maxSizeMB), _isDraining(isDraining) { _setAddr(addr); - - BSONArrayIteratorSorted iter(tags); - while (iter.more()) { - BSONElement tag = iter.next(); - _tags.insert(tag.String()); - } } Shard::Shard(const std::string& name, const ConnectionString& connStr, long long maxSizeMB, - bool isDraining, - const set<string>& tags): + bool isDraining): _name(name), _addr(connStr.toString()), _cs(connStr), _maxSizeMB(maxSizeMB), - _isDraining(isDraining), - _tags(tags) { + _isDraining(isDraining) { } Shard Shard::findIfExists( const string& shardName ) { @@ -450,22 +440,46 @@ namespace mongo { return res; } - ShardStatus Shard::getStatus() const { - BSONObj serverStatus = runCommand("admin", BSON("serverStatus" << 1)); + string Shard::getShardMongoVersion(const string& shardHost) { + ScopedDbConnection conn(shardHost); + BSONObj serverStatus; + bool ok = conn->runCommand("admin", BSON("serverStatus" << 1), serverStatus); + conn.done(); + + uassert(28598, + str::stream() << "call to serverStatus on " << shardHost + << " failed: " << serverStatus, + ok); + BSONElement versionElement = serverStatus["version"]; uassert(28589, "version field not found in serverStatus", versionElement.type() == String); - string version = serverStatus["version"].String(); + return serverStatus["version"].String(); + } + + long long Shard::getShardDataSizeBytes(const string& shardHost) { + ScopedDbConnection conn(shardHost); + BSONObj listDatabases; + bool ok = conn->runCommand("admin", BSON("listDatabases" << 1), listDatabases); + conn.done(); + + uassert(28599, + str::stream() << "call to listDatabases on " << shardHost + << " failed: " << listDatabases, + ok); - BSONObj listDatabases = runCommand("admin", BSON("listDatabases" << 1)); BSONElement totalSizeElem = listDatabases["totalSize"]; uassert(28590, "totalSize field not found in listDatabases", totalSizeElem.isNumber()); - long long dataSizeBytes = listDatabases["totalSize"].numberLong(); + return listDatabases["totalSize"].numberLong(); + } - return ShardStatus(*this, dataSizeBytes, version); + ShardStatus Shard::getStatus() const { + return ShardStatus(*this, + getShardDataSizeBytes(getConnString()), + getShardMongoVersion(getConnString())); } void Shard::reloadShardInfo() { diff --git a/src/mongo/s/shard.h b/src/mongo/s/shard.h index a627c0e19dd..7f1f6ffadae 100644 --- a/src/mongo/s/shard.h +++ b/src/mongo/s/shard.h @@ -57,14 +57,12 @@ namespace mongo { Shard(const std::string& name, const std::string& addr, long long maxSizeMB, - bool isDraining, - const BSONArray& tags); + bool isDraining); Shard(const std::string& name, const ConnectionString& connStr, long long maxSizeMB, - bool isDraining, - const std::set<std::string>& tags); + bool isDraining); Shard( const std::string& ident ) { reset( ident ); @@ -75,8 +73,7 @@ namespace mongo { _addr(other._addr), _cs(other._cs), _maxSizeMB(other._maxSizeMB), - _isDraining(other._isDraining), - _tags(other._tags) { + _isDraining(other._isDraining) { } static Shard make( const std::string& ident ) { @@ -150,8 +147,21 @@ namespace mongo { } BSONObj runCommand( const std::string& db , const BSONObj& cmd ) const ; + /** + * Returns the version string from the shard based from the serverStatus command result. + */ + static std::string getShardMongoVersion(const std::string& shardHost); + + /** + * Returns the total data size in bytes the shard is currently using. + */ + static long long getShardDataSizeBytes(const std::string& shardHost); + + /** + * Returns metadata and stats for this shard. + */ ShardStatus getStatus() const ; - + /** * mostly for replica set * retursn true if node is the shard @@ -159,8 +169,6 @@ namespace mongo { */ bool containsNode( const std::string& node ) const; - const std::set<std::string>& tags() const { return _tags; } - static void getAllShards( std::vector<Shard>& all ); static void printShardInfo( std::ostream& out ); static Shard lookupRSName( const std::string& name); @@ -190,7 +198,6 @@ namespace mongo { ConnectionString _cs; long long _maxSizeMB; // in MBytes, 0 is unlimited bool _isDraining; // shard is currently being removed - std::set<std::string> _tags; }; typedef boost::shared_ptr<Shard> ShardPtr; diff --git a/src/mongo/s/shard_test.cpp b/src/mongo/s/shard_test.cpp index 0e90f86e408..ff1fccc88d6 100644 --- a/src/mongo/s/shard_test.cpp +++ b/src/mongo/s/shard_test.cpp @@ -34,23 +34,23 @@ namespace mongo { TEST( Shard, EqualityRs ) { - Shard a("foo", "bar/a,b", 0, false, BSONArray()); - Shard b("foo", "bar/a,b", 0, false, BSONArray()); + Shard a("foo", "bar/a,b", 0, false); + Shard b("foo", "bar/a,b", 0, false); ASSERT_EQUALS( a, b ); - b = Shard("foo", "bar/b,a", 0, false, BSONArray()); + b = Shard("foo", "bar/b,a", 0, false); ASSERT_EQUALS( a, b ); } TEST( Shard, EqualitySingle ) { - ASSERT_EQUALS(Shard("foo", "b.foo.com:123", 0, false, BSONArray()), - Shard("foo", "b.foo.com:123", 0, false, BSONArray())); - ASSERT_NOT_EQUALS(Shard("foo", "b.foo.com:123", 0, false, BSONArray()), - Shard("foo", "a.foo.com:123", 0, false, BSONArray())); - ASSERT_NOT_EQUALS(Shard("foo", "b.foo.com:123", 0, false, BSONArray()), - Shard("foo", "b.foo.com:124", 0, false, BSONArray())); - ASSERT_NOT_EQUALS(Shard("foo", "b.foo.com:123", 0, false, BSONArray()), - Shard("foa", "b.foo.com:123", 0, false, BSONArray())); + ASSERT_EQUALS(Shard("foo", "b.foo.com:123", 0, false), + Shard("foo", "b.foo.com:123", 0, false)); + ASSERT_NOT_EQUALS(Shard("foo", "b.foo.com:123", 0, false), + Shard("foo", "a.foo.com:123", 0, false)); + ASSERT_NOT_EQUALS(Shard("foo", "b.foo.com:123", 0, false), + Shard("foo", "b.foo.com:124", 0, false)); + ASSERT_NOT_EQUALS(Shard("foo", "b.foo.com:123", 0, false), + Shard("foa", "b.foo.com:123", 0, false)); } TEST( Shard, EqualitySync ) { 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() { |