MongoDB支持自动分片,可以摆脱手动分片的管理困扰。集群自动切分数据,做负载均衡。以下为单机搭建的测试环境。

1.创建数据库目录与日志目录
 
useradd mongo
mkdir -p /database/data/mongodb_data
mkdir -p /database/data/logs
mkdir -p /database/data/key
chown mongo.mongo /database/data/mongodb_data/
su - mongo
mkdir -p /database/data/mongodb_data/shard1_1
mkdir -p /database/data/mongodb_data/shard1_2
mkdir -p /database/data/mongodb_data/shard1_3
mkdir -p /database/data/mongodb_data/shard2_1
mkdir -p /database/data/mongodb_data/shard2_2
mkdir -p /database/data/mongodb_data/shard2_3
mkdir -p /database/data/mongodb_data/shard3_1
mkdir -p /database/data/mongodb_data/shard3_2
mkdir -p /database/data/mongodb_data/shard3_3
mkdir -p /database/data/mongodb_data/config1
mkdir -p /database/data/mongodb_data/config2
mkdir -p /database/data/mongodb_data/config3
 
2.创建KeyFIle文件
 
Sharding开启认证需要v1.9.1+ 
mkdir -p /database/data/key
echo "AABIwAA AQEArfcoY JYsGYg62tH n31uuJMr6AX Pr0rVA3Hkk" > /database/data/key/shard1_1
echo "AABIwAA AQEArfcoY JYsGYg62tH n31uuJMr6AX Pr0rVA3Hkk" > /database/data/key/shard1_2
echo "AABIwAA AQEArfcoY JYsGYg62tH n31uuJMr6AX Pr0rVA3Hkk" > /database/data/key/shard1_3
echo "AABIwAA AQEArfcoY JYsGYg62tH n31uuJMr6AX Pr0rVA3Hkk" > /database/data/key/shard2_1
echo "AABIwAA AQEArfcoY JYsGYg62tH n31uuJMr6AX Pr0rVA3Hkk" > /database/data/key/shard2_2
echo "AABIwAA AQEArfcoY JYsGYg62tH n31uuJMr6AX Pr0rVA3Hkk" > /database/data/key/shard2_3
echo "AABIwAA AQEArfcoY JYsGYg62tH n31uuJMr6AX Pr0rVA3Hkk" > /database/data/key/shard3_1
echo "AABIwAA AQEArfcoY JYsGYg62tH n31uuJMr6AX Pr0rVA3Hkk" > /database/data/key/shard3_2
echo "AABIwAA AQEArfcoY JYsGYg62tH n31uuJMr6AX Pr0rVA3Hkk" > /database/data/key/shard3_3
echo "AABIwAA AQEArfcoY JYsGYg62tH n31uuJMr6AX Pr0rVA3Hkk" > /database/data/key/config1
echo "AABIwAA AQEArfcoY JYsGYg62tH n31uuJMr6AX Pr0rVA3Hkk" > /database/data/key/config2
echo "AABIwAA AQEArfcoY JYsGYg62tH n31uuJMr6AX Pr0rVA3Hkk" > /database/data/key/config3
echo "AABIwAA AQEArfcoY JYsGYg62tH n31uuJMr6AX Pr0rVA3Hkk" > /database/data/key/mongos1
echo "AABIwAA AQEArfcoY JYsGYg62tH n31uuJMr6AX Pr0rVA3Hkk" > /database/data/key/mongos2
chmod 600 /database/data/key/*
 
3.搭建Replica Set
 
su - mongo
 
echo "export PATH=$PATH:/database/servers/mongodb/bin" >> ~/.bash_profile
echo "export LANG=en_US.UTF-8" >> ~/.bash_profile
source ~/.bash_profile
 
/database/servers/mongo/bin/mongod --replSet shard1 --keyFile /database/data/key/shard1_1 --port 20011 --dbpath /database/data/mongodb_data/shard1_1/ --logpath /database/data/logs/shard1_1.log --logappend --oplogSize 100 --rest --directoryperdb --fork
 
/database/servers/mongo/bin/mongod --replSet shard1 --keyFile /database/data/key/shard1_2 --port 20012 --dbpath /database/data/mongodb_data/shard1_2/ --logpath /database/data/logs/shard1_2.log --logappend --oplogSize 100 --rest --directoryperdb --fork
 
/database/servers/mongo/bin/mongod --replSet shard1 --keyFile /database/data/key/shard1_3 --port 20013 --dbpath /database/data/mongodb_data/shard1_3/ --logpath /database/data/logs/shard1_3.log --logappend --oplogSize 100 --rest --directoryperdb --fork
 
mongo --port 20011
> config = {_id: 'shard1', members: [{_id: 0, host: '127.0.0.1:20011'},{_id: 1, host: '127.0.0.1:20012'},{_id: 2, host:'127.0.0.1:20013'}]}
> rs.initiate(config)
> rs.status()
 
> use admin
> db.addUser("admin","123")
 
插入测试数据
> use test
> for (var i=0;i<1000000;++i) db.test.insert({name:"mongo",x:i})
> db.test.ensureIndex({x:1})
 
4.搭建Replica Set2
 
/database/servers/mongo/bin/mongod --replSet shard2 --keyFile /database/data/key/shard2_1 --port 20021 --dbpath /database/data/mongodb_data/shard2_1/ --logpath /database/data/logs/shard2_1.log --logappend --oplogSize 100 --rest --directoryperdb --fork
 
/database/servers/mongo/bin/mongod --replSet shard2 --keyFile /database/data/key/shard2_2 --port 20022 --dbpath /database/data/mongodb_data/shard2_2/ --logpath /database/data/logs/shard2_2.log --logappend --oplogSize 100 --rest --directoryperdb --fork
 
/database/servers/mongo/bin/mongod --replSet shard2 --keyFile /database/data/key/shard2_3 --port 20023 --dbpath /database/data/mongodb_data/shard2_3/ --logpath /database/data/logs/shard2_3.log --logappend --oplogSize 100 --rest --directoryperdb --fork
 
mongo --port 20021
> config = {_id: 'shard2', members: [{_id: 0, host: '127.0.0.1:20021'},{_id: 1, host: '127.0.0.1:20022'},{_id: 2, host:'127.0.0.1:20023'}]}
> rs.initiate(config)
> rs.status()
 
> use admin
> db.addUser("admin","123")
 
5.扩展为Sharding
 
配置服务器使用的是两步提交机制,而不是普通MongoDB的异步复制,来维护集群配置的不同副本。这样能保证集群状态的一致性。这也意味着,某台配置服务器宕掉了以后,集群配置信息将是只读的。客户端还是能够读写,但是只有所有配置服务器备份了以后才能重新均衡数据。
/database/servers/mongo/bin/mongod --configsvr --keyFile /database/data/key/config1 --dbpath /database/data/mongodb_data/config1 --port 40001 --logpath /database/data/logs/config1.log --logappend --fork
/database/servers/mongo/bin/mongod --configsvr --keyFile /database/data/key/config2 --dbpath /database/data/mongodb_data/config2 --port 40002 --logpath /database/data/logs/config2.log --logappend --fork
/database/servers/mongo/bin/mongod --configsvr --keyFile /database/data/key/config3 --dbpath /database/data/mongodb_data/config3 --port 40003 --logpath /database/data/logs/config3.log --logappend --fork
 
/database/servers/mongo/bin/mongos  --keyFile /database/data/key/mongos1 --configdb 127.0.0.1:40001,127.0.0.1:40002,127.0.0.1:40003 --port 30001 --logpath /database/data/logs/mongos1.log --logappend --fork
/database/servers/mongo/bin/mongos  --keyFile /database/data/key/mongos2 --configdb 127.0.0.1:40001,127.0.0.1:40002,127.0.0.1:40003 --port 30002 --logpath /database/data/logs/mongos2.log --logappend --fork
 
6.添加片并切分数据
 
mongo --port 30001
> use admin
> db.addUser("admin","123")
> db.auth("admin","123")
> db.runCommand({addshard:"shard1/127.0.0.1:20011,127.0.0.1:20012,127.0.0.1:20013"});
> db.runCommand({addshard:"shard2/127.0.0.1:20021,127.0.0.1:20022,127.0.0.1:20023"});
> db.runCommand({ enablesharding:"test" })
> db.runCommand({ shardcollection: "test.test", key: { x:1 }})
> db.runCommand({ enablesharding:"aaa" })
> db.runCommand({ shardcollection: "aaa.ddd", key: { x:1 }})
> use test
> for (var i=0;i<1000000;++i) db.ddd.insert({name:"mongo",x:i})
 
7.查看
 
mongos> db.currentOP()
 
{
"opid" : "shard1:1930919",
"active" : true,
"lockType" : "read",
"waitingForLock" : false,
"secs_running" : 72,
"op" : "query",
"ns" : "test.test",
"query" : {
"moveChunk" : "test.test",
"from" : "shard1/127.0.0.1:20011,127.0.0.1:20013,127.0.0.1:20012",
"to" : "shard2/127.0.0.1:20021,127.0.0.1:20023,127.0.0.1:20022",
"min" : {
"x" : 1372800
},
"max" : {
"x" : { $maxKey : 1 }
},
"maxChunkSizeBytes" : NumberLong(67108864),
"shardId" : "test.test-x_1372800.0",
"configdb" : "127.0.0.1:40001"
},
"client_s" : "127.0.0.1:45242",
"desc" : "conn",
"threadId" : "0x4bfd0940",
"connectionId" : 29,
"msg" : "step3",
"numYields" : 0
}
moveChunk正在移动
 
mongos> db.printShardingStatus()
--- Sharding Status --- 
  sharding version: { "_id" : 1, "version" : 3 }
  shards:
{  "_id" : "shard1",  "host" : "shard1/127.0.0.1:20011,127.0.0.1:20013,127.0.0.1:20012" }
{  "_id" : "shard2",  "host" : "shard2/127.0.0.1:20021,127.0.0.1:20023,127.0.0.1:20022" }
  databases:
{  "_id" : "admin",  "partitioned" : false,  "primary" : "config" }
{  "_id" : "test",  "partitioned" : true,  "primary" : "shard1" }
test.test chunks:
shard1 3
shard2 1
{ "x" : { $minKey : 1 } } -->> { "x" : 0 } on : shard1 { "t" : 2000, "i" : 1 }
{ "x" : 0 } -->> { "x" : 1000002 } on : shard1 { "t" : 1000, "i" : 3 }
{ "x" : 1000002 } -->> { "x" : 1372800 } on : shard1 { "t" : 1000, "i" : 5 }
{ "x" : 1372800 } -->> { "x" : { $maxKey : 1 } } on : shard2 { "t" : 2000, "i" : 0 }
{  "_id" : "aaa",  "partitioned" : true,  "primary" : "shard2" }
aaa.ddd chunks:
shard2 5
shard1 2
{ "x" : { $minKey : 1 } } -->> { "x" : 0 } on : shard2 { "t" : 2000, "i" : 1 }
{ "x" : 0 } -->> { "x" : 362389 } on : shard2 { "t" : 1000, "i" : 3 }
{ "x" : 362389 } -->> { "x" : 724778 } on : shard2 { "t" : 1000, "i" : 5 }
{ "x" : 724778 } -->> { "x" : 1087167 } on : shard2 { "t" : 1000, "i" : 7 }
{ "x" : 1087167 } -->> { "x" : 1449556 } on : shard2 { "t" : 1000, "i" : 9 }
{ "x" : 1449556 } -->> { "x" : 1811945 } on : shard1 { "t" : 2000, "i" : 2 }
{ "x" : 1811945 } -->> { "x" : { $maxKey : 1 } } on : shard1 { "t" : 2000, "i" : 3 }
分片信息
 
8.添加新的片
 
/database/servers/mongo/bin/mongod --replSet shard3 --keyFile /database/data/key/shard3_1 --port 20031 --dbpath /database/data/mongodb_data/shard3_1/ --logpath /database/data/logs/shard3_1.log --logappend --oplogSize 100 --rest --directoryperdb --fork
 
/database/servers/mongo/bin/mongod --replSet shard3 --keyFile /database/data/key/shard3_2 --port 20032 --dbpath /database/data/mongodb_data/shard3_2/ --logpath /database/data/logs/shard3_2.log --logappend --oplogSize 100 --rest --directoryperdb --fork
 
/database/servers/mongo/bin/mongod --replSet shard3 --keyFile /database/data/key/shard3_3 --port 20033 --dbpath /database/data/mongodb_data/shard3_3/ --logpath /database/data/logs/shard3_3.log --logappend --oplogSize 100 --rest --directoryperdb --fork
 
mongo --port 20031
> config = {_id: 'shard3', members: [{_id: 0, host: '127.0.0.1:20031'},{_id: 1, host: '127.0.0.1:20032'},{_id: 2, host:'127.0.0.1:20033'}]}
> rs.initiate(config)
> rs.status()
> use admin
> db.addUser("admin","123")
 
mongo --port 30001
> use admin
> db.auth("admin","123")
> db.runCommand({addshard:"shard3/127.0.0.1:30021,127.0.0.1:20032,127.0.0.1:20033"});
 
9.操作类型
 
shard key为{x:1}

OperationType Comments 
db.foo.find( { x : 300 } ) Targeted Queries a single shard. 
db.foo.find( { x : 300, age : 40 } )TargetedQueries a single shard. 
db.foo.find( { age : 40 } ) GlobalQueries all shards. 
db.foo.find() Globalsequential 
db.foo.find(...).count() VariableSame as the corresponding find() operation
db.foo.find(...).sort( { age : 1 } ) Globalparallel
db.foo.find(...).sort( { x : 1 } ) Globalsequential
db.foo.count() Globalparallel
db.foo.insert( <object> ) Targeted 
db.foo.update( { x : 100 }, <object> ) 
db.foo.remove( { x : 100 } ) 
Targeted 
db.foo.update( { age : 40 }, <object> ) 
db.foo.remove( { age : 40 } ) 
Global  
db.getLastError()   
db.foo.ensureIndex(...) Global