1)架构图:
2)四个组件:mongos、config server、shard、replica set
mongos,数据库集群请求的入口,所有的请求都通过mongos进行协调,不需要在应用程序添加一个路由选择器,mongos自己就是一个请求分发中心,它负责把对应的数据请求请求转发到对应的shard服务器上。在生产环境通常有多mongos作为请求的入口,防止其中一个挂掉所有的mongodb请求都没有办法操作。
config server,顾名思义为配置服务器,存储所有数据库元信息(路由、分片)的配置。
Shard,和大数据存储HDFS分片存储的思想的东西。
Replica set,副本集服务器。
3)准备环境:
ip:192.168.30.131
ip:192.168.30.132
ip:192.168.30.134
4)在每台机器上建立mongos、config、shard1、shard2、shard3五个目录。
#建立mongos目录
mkdir -p /data/mongodbtest/mongos
#建立config server 数据文件存放目录
mkdir -p /data/mongodbtest/config/data
#建立config server 日志文件存放目录
mkdir -p /data/mongodbtest/config/log
#建立config server 日志文件存放目录
mkdir -p /data/mongodbtest/mongos/log
#建立shard1 数据文件存放目录
mkdir -p /data/mongodbtest/shard1/data
#建立shard1 日志文件存放目录
mkdir -p /data/mongodbtest/shard1/log
#建立shard2 数据文件存放目录
mkdir -p /data/mongodbtest/shard2/data
#建立shard2 日志文件存放目录
mkdir -p /data/mongodbtest/shard2/log
#建立shard3 数据文件存放目录
mkdir -p /data/mongodbtest/shard3/data
#建立shard3 日志文件存放目录
mkdir -p /data/mongodbtest/shard3/log
cd /data/mongodbtest
5)安装mongodb
这里不多说了,看上个文章,还是在/data/mongodbtest/single里
6)规划5个组件对应的端口号,由于一个机器需要同时部署 mongos、config server 、shard1、shard2、shard3,所以需要用端口进行区分。
这个端口可以自由定义,在本文 mongos为 20000, config server 为 21000, shard1为 22001 , shard2为22002, shard3为22003.
参数说明:
dbpath:数据存放目录
logpath:日志存放路径 logappend:以追加的方式记录日志
replSet:replica set 的名字
port:mongodb 进程所使用的端口号,默认为 27017 fork:以后台方式运行进程
journal:写日志
smallfiles:当提示空间不够时添加此参数
其他参数
pidfilepath:进程文件,方便停止 mongodbdirectoryperdb:为每一个数据库按照数据库名建立文件夹存放 bind_ip:mongodb 所绑定的 ip 地址
oplogSize:mongodb 操作日志文件的最大大小。单位为 Mb,默认为硬盘剩余空间的 5%
noprealloc:不预先分配存储
shardsvr:分片
configsvr:配置服务节点
configdb:配置 config 节点到 route 节点
7)在每台机器上启动配置服务器
/data/mongodbtest/single/mongodb/bin/mongod --dbpath /data/mongodbtest/config/data/ --configsvr --port 21000 --logpath /data/mongodbtest/config/log/config.log –fork
8)在每台服务器上启动mongos服务器
/data/mongodbtest/single/mongodb/bin/mongos --configdb 192.168.30.134:21000,192.168.30.132:21000,192.168.30.131:21000 --port 20000 --logpath /data/mongodbtest/mongos/log/mongos.log –fork
9)配置各个分片的副本集
#在每个机器里分别设置分片1服务器及副本集shard1
/data/mongodbtest/single/mongodb/bin/mongod --shardsvr --replSet shard1 --port 22001 --dbpath /data/mongodbtest/shard1/data --logpath /data/mongodbtest/shard1/log/shard1.log --fork -nojournal --oplogSize 10
#在每个机器里分别设置分片2服务器及副本集shard2
/data/mongodbtest/single/mongodb/bin/mongod --shardsvr --replSet shard2 --port 22002 --dbpath /data/mongodbtest/shard2/data --logpath /data/mongodbtest/shard2/log/shard2.log --fork -nojournal --oplogSize 10
#在每个机器里分别设置分片3服务器及副本集shard3
/data/mongodbtest/single/mongodb/bin/mongod --shardsvr --replSet shard3 --port 22003 --dbpath /data/mongodbtest/shard3/data --logpath /data/mongodbtest/shard3/log/shard3.log --fork -nojournal --oplogSize 10
任意登陆一个机器,比如登陆192.168.30.131,连接mongodb
#设置第一个分片副本集
/data/mongodbtest/single/mongodb/bin/mongo 127.0.0.1:22001
> use admin;
switched to db admin
#定义副本集配置
>config={_id:"shard1",members:[
... {_id:0,host:"192.168.30.131:22001"},
... {_id:1,host:"192.168.30.132:22001"},
... {_id:2,host:"192.168.30.134:22001",arbiterOnly:true}]#指定仲裁节点
... }
{
"_id" : "shard1",
"members" : [
{
"_id" : 0,
"host" : "192.168.30.131:22001"
},
{
"_id" : 1,
"host" : "192.168.30.132:22001"
},
{
"_id" : 2,
"host" : "192.168.30.134:22001",
"arbiterOnly" : true
}
]
}
#初始化副本集配置
>rs.initiate(config);
#设置第二个分片副本集
/data/mongodbtest/single/mongodb/bin/mongo 127.0.0.1:22002
> use admin;
>config={_id:"shard2",members:[
... {_id:0,host:"192.168.30.131:22002"},
... {_id:1,host:"192.168.30.132:22002"},
... {_id:2,host:"192.168.30.134:22002",arbiterOnly:true}]
... }
>rs.initiate(config);
#设置第三个分片副本集
/data/mongodbtest/single/mongodb/bin/mongo 127.0.0.1:22003
> use admin;
>config={_id:"shard3",members:[
... {_id:0,host:"192.168.30.131:22003"},
... {_id:1,host:"192.168.30.132:22003"},
... {_id:2,host:"192.168.30.134:22003",arbiterOnly:true}]
... }
>rs.initiate(config);
10)设置分片配置且生效
/data/mongodbtest/single/mongodb/bin/mongo 127.0.0.1:20000
mongos> use admin;
#串联路由服务器与分配副本集1、2、3
#如里shard是单台服务器,用db.runCommand( { addshard : “[: ]” } )命令,如果shard是副本集,用db.runCommand( { addshard : “replicaSetName/[:port][,serverhostname2[:port],…]” });格式
mongos> db.runCommand({addshard:"shard1/192.168.30.131:22001,192.168.30.132:22001,192.168.30.134:22001"});
{ "shardAdded" : "shard1", "ok" : 1 }
mongos> db.runCommand({addshard:"shard2/192.168.30.131:22002,192.168.30.132:22002,192.168.30.134:22002"});
{ "shardAdded" : "shard2", "ok" : 1 }
mongos> db.runCommand({addshard:"shard3/192.168.30.131:22003,192.168.30.132:22003,192.168.30.134:22003"});
{ "shardAdded" : "shard3", "ok" : 1 }
#查看分片服务器的配置
mongos>db.runCommand({listshards:1});
{
"shards" : [
{
"_id" : "shard1",
"host" : "shard1/192.168.30.131:22001,192.168.30.132:22001"
},
{
"_id" : "shard2",
"host" : "shard2/192.168.30.131:22002,192.168.30.132:22002"
},
{
"_id" : "shard3",
"host" : "shard3/192.168.30.131:22003,192.168.30.132:22003"
}
],
"ok" : 1
}
注:因为192.168.30.134是每个分片副本集的仲裁节点,所以在上面结果没有列出来。
11)指定的数据库和集合分片生效
/data/mongodbtest/single/mongodb/bin/mongo 127.0.0.1:20000
mongos> use admin;
#指定testdb库分片生效
mongos>db.runCommand({enablesharding:"testdb"});
{ "ok" : 1 }
#指定数据库里需要分片的集合和片键,片键为id且唯一
mongos> db.runCommand({shardcollection:"testdb.teble1",key:{id:1},unique:true});
{ "collectionsharded" : "testdb.teble1", "ok" : 1 }
12)测试分布配置是否成功:
mongos> use testdb;
#插入测试数据
mongos> for(var i=1;i<=5000;i++) db.teble1.save({id:i,"test1":"testval1"});
WriteResult({ "nInserted" : 1 })
#查看分片情况
mongos> db.teble1.stats()
{
"sharded" : true,
"paddingFactorNote" : "paddingFactor is unused and unmaintained in 3.0. It remains hard coded to 1.0 for compatibility only.",
"userFlags" : 1,
"capped" : false,
"ns" : "testdb.teble1",
"count" : 5000,
"numExtents" : 6,
"size" : 560000,
"storageSize" : 712704,
"totalIndexSize" : 351568,
"indexSizes" : {
"_id_" : 188048,
"id_1" : 163520
},
"avgObjSize" : 112,
"nindexes" : 2,
"nchunks" : 3,
"shards" : {
"shard1" : {
"ns" : "testdb.teble1",
"count" : 4991,
"size" : 558992,
"avgObjSize" : 112,
"numExtents" : 4,
……#省略
},
"shard2" : {
"ns" : "testdb.teble1",
"count" : 1,
"size" : 112,
"avgObjSize" : 112,
"numExtents" : 1,
"storageSize" : 8192,
"lastExtentSize" : 8192,
……
},
"shard3" : {
"ns" : "testdb.teble1",
"count" : 8,
"size" : 896,
"avgObjSize" : 112,
"numExtents" : 1,
"storageSize" : 8192,
"lastExtentSize" : 8192,
…….
}
},
"ok" : 1
}
13)java程序调用分片集群
public class TestMongoDBShards {
public static void main(String[] args) {
try {
List<ServerAddress> addresses = new ArrayList<ServerAddress>();
ServerAddress address1 = new ServerAddress("192.168.30.131" , 20000);
ServerAddress address2 = new ServerAddress("192.168.30.132" , 20000);
ServerAddress address3 = new ServerAddress("192.168.30.134" , 20000);
addresses.add(address1);
addresses.add(address2);
addresses.add(address3);
MongoClient client = new MongoClient(addresses);
DB db = client.getDB( "testdb" );
DBCollectioncoll = db.getCollection( "table1" );
BasicDBObject object = new BasicDBObject();
object.append( "id" , 1);
DBObjectdbObject = coll.findOne(object);
System.out .println(dbObject);
} catch (Exception e) {
e.printStackTrace();
}
}
}
方案缺陷:
仲裁节点很闲,而主从节点承担全部读写压力,是服务器负载不均衡,资源浪费。
方案改型成,如下: