summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandolph Tan <randolph@10gen.com>2015-01-06 14:22:58 -0500
committerRandolph Tan <randolph@10gen.com>2015-01-06 17:42:48 -0500
commit293bf1caf51df5b9cf7c882f2e6312769e1716a2 (patch)
treec31bfee5f41ff3c93558b2e097a7c277ffdfc7ac
parent4b7a350224eef7676b4c49e2616bc2bee347420f (diff)
downloadmongo-293bf1caf51df5b9cf7c882f2e6312769e1716a2.tar.gz
SERVER-16683 Decrease mongos memory footprint when shards have several tags
-rw-r--r--src/mongo/s/balance.cpp20
-rw-r--r--src/mongo/s/balancer_policy.cpp126
-rw-r--r--src/mongo/s/balancer_policy.h5
-rw-r--r--src/mongo/s/chunk.cpp19
-rw-r--r--src/mongo/s/shard.cpp7
-rw-r--r--src/mongo/s/shard.h7
-rw-r--r--src/mongo/s/type_shard.cpp4
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() {