# MongoDB 集群部署

## 关键词

* 集群

* 副本集

* 分片

## MongoDB集群部署

>今天主要来说说Mongodb的三种集群方式的搭建Replica Set副本集分片主备。

 

### Replica Set副本集

>其实简单来说就是集群当中包含了多份数据,保证主节点挂掉了,备节点能继续提供数据服务,提供的前提就是数据需要和主节点一致

 

![集群部署](monog.jpg)

 

>Mongodb(M)表示主节点,Mongodb(S)表示备节点,Mongodb(A)表示仲裁节点。主备节点存储数据,仲裁节点不存储数据。客户端同时连接主节点与备节点,不连接仲裁节点。

 

>默认设置下,主节点提供所有增删查改服务,备节点不提供任何服务。但是可以通过设置使备节点提供查询服务,这样就可以减少主节点的压力,当客户端进行数据查询时,请求自动转到备节点上。这个设置叫做Read Preference Modes,同时Java客户端提供了简单的配置方式,可以不必直接对数据库进行操作。

 

>仲裁节点是一种特殊的节点,它本身并不存储数据,主要的作用是决定哪一个备节点在主节点挂掉之后提升为主节点,所以客户端不需要连接此节点。这里虽然只有一个备节点,但是仍然需要一个仲裁节点来提升备节点级别。我开始也不相信必须要有仲裁节点,但是自己也试过没仲裁节点的话,主节点挂了备节点还是备节点,所以咱们还是需要它的。

介绍完了集群方案,那么现在就开始搭建了。

 

1.建立数据文件夹

 

一般情况下不会把数据目录建立在mongodb的解压目录下,不过这里方便起见,就建在mongodb解压目录下吧。

 

```js

mkdir -p /mongodb/data/Master

mkdir -p /mongodb/data/slaver 

mkdir -p /mongodb/data/arbiter  

三个目录分别对应主,备,仲裁节点

```

 

2.建立配置文件

由于配置比较多,所以我们将配置写到文件里。

 

```js  
dbpath=/mongodb/data/master  
logpath=/mongodb/log/master.log  
pidfilepath=/mongodb/master.pid  
directoryperdb=true  
logappend=true  
replSet=testrs  
bind_ip=10.10.29.136  
port=27017  
oplogSize=10000  
fork=true  
noprealloc=true
```

 

参数解释:

dbpath:数据存放目录

logpath:日志存放路径

pidfilepath:进程文件,方便停止mongodb

directoryperdb:为每一个数据库按照数据库名建立文件夹存放

logappend:以追加的方式记录日志

replSet:replica set的名字

bind_ip:mongodb所绑定的ip地址

port:mongodb进程所使用的端口号,默认为27017

oplogSize:mongodb操作日志文件的最大大小。单位为Mb,默认为硬盘剩余空间的5%

fork:以后台方式运行进程

noprealloc:不预先分配存储

 

 

3.启动mongodb

进入每个mongodb节点的bin目录下

 

```js
./monood -f master.conf  
./mongod -f slaver.conf  
./mongod -f arbiter.conf 
```

 

注意配置文件的路径一定要保证正确,可以是相对路径也可以是绝对路径。

 

4.配置主,备,仲裁节点

可以通过客户端连接mongodb,也可以直接在三个节点中选择一个连接mongodb。

 

```js
./mongo 10.10.29.136:27017   #ip和port是某个节点的地址  
>use admin  
>cfg={ _id:"testrs", members:[ {_id:0,host:'10.10.29.136:27017',priority:2}, {_id:1,host:'10.10.29.131:27017',priority:1},   
{_id:2,host:'10.10.29.132:27017',arbiterOnly:true}] };  
>rs.initiate(cfg)             #使配置生效 
```

 

>cfg是自己定义的,当然最好不要是mongodb的关键字,conf,config都可以。

 

>最外层的_id表示replica set的名字,members里包含的是所有节点的地址以及优先级。优先级最高的即成为主节点,即这里的10.10.148.130:27017。特别注意的是,对于仲裁节点,需要有个特别的配置——arbiterOnly:true。这个千万不能少了,不然主备模式就不能生效。

 

>配置的生效时间根据不同的机器配置会有长有短,配置不错的话基本上十几秒内就能生效,有的配置需要一两分钟。如果生效了,执行rs.status()命令会看到如下信息:

```js
{  
        "set" : "testrs",  
        "date" : ISODate("2013-01-05T02:44:43Z"),  
        "myState" : 1,  
        "members" : [  
                {  
                        "_id" : 0,  
                        "name" : "10.10.148.130:27017",  
                        "health" : 1,  
                        "state" : 1,  
                        "stateStr" : "PRIMARY",  
                        "uptime" : 200,  
                        "optime" : Timestamp(1357285565000, 1),  
                        "optimeDate" : ISODate("2013-01-04T07:46:05Z"),  
                        "self" : true  
                },  
                {  
                        "_id" : 1,  
                        "name" : "10.10.148.131:27017",  
                        "health" : 1,  
                        "state" : 2,  
                        "stateStr" : "SECONDARY",  
                        "uptime" : 200,  
                        "optime" : Timestamp(1357285565000, 1),  
                        "optimeDate" : ISODate("2013-01-04T07:46:05Z"),  
                        "lastHeartbeat" : ISODate("2013-01-05T02:44:42Z"),  
                        "pingMs" : 0  
                },  
                {  
                        "_id" : 2,  
                        "name" : "10.10.148.132:27017",  
                        "health" : 1,  
                        "state" : 7,  
                        "stateStr" : "ARBITER",  
                        "uptime" : 200,  
                        "lastHeartbeat" : ISODate("2013-01-05T02:44:42Z"),  
                        "pingMs" : 0  
                }  
        ],  
        "ok" : 1  
}  
```

 

同时可以查看对应节点的日志,发现正在等待别的节点生效或者正在分配数据文件。

 

>现在基本上已经完成了集群的所有搭建工作。一个是往主节点插入数据,能从备节点查到之前插入的数据。二是停掉主节点,备节点能变成主节点提供服务。三是恢复主节点,备节点也能恢复其备的角色,而不是继续充当主的角色。二和三都可以通过rs.status()命令实时查看集群的变化。100G数据以下建议用副本集,高并发下备节点同步数据是需要时间的

 

### Sharding分片

 

这就是传说中的分片了。上面提到一个机器就算能力再大也有天花板,就像军队打仗一样,一个人再厉害喝血瓶也拼不过对方的一个师。俗话说三个臭皮匠顶个诸葛亮,这个时候团队的力量就凸显出来了。在互联网也是这样,一台普通的机器做不了的多台机器来做,如下图

 

分片](fenpian.jpg)

 

>一台机器的一个数据表存储了数据,压力太大了!在分给4个机器后,每个机器都是256G,则分摊了集中在一台机器的压力。也许有人问一台机器硬盘加大一点不就可以了,为什么要分给四台机器呢?不要光想到存储空间,实际运行的数据库还有硬盘的读写、网络的IO、CPU和内存的瓶颈。在mongodb集群只要设置好了分片规则,通过mongos操作数据库就能自动把对应的数据操作请求转发到对应的分片机器上。在生产环境中分片的片键可要好好设置,这个影响到了怎么把数据均匀分到多个分片机器上,不要出现其中一台机器分了1T,其他机器没有分到的情况,这样还不如不分片!

 

搭建集群具体步骤:

首先确定各个组件的数量,mongos 3个,个,数据分3片个,每个shard 有一个副本一个仲裁也就是个,总共需要部署15个实例。这些实例可以部署在独立机器也可以部署在一台机器,我们这里测试资源有限,只准备了台机器,在同一台机器只要端口不同就可以,看一下物理部署图:

 

![分片](fenpian1.jpg)

 

架构搭好了,安装软件!

 

1、准备机器,IP分别设置为:、192.168.0.137、192.168.0.138。

2、分别在每台机器上建立mongodb分片对应文件夹。

3、下载mongodb的安装程序包

4、分别在每台机器建立mongos 、config 、、shard2、shard3 五个目录。

因为mongos不存储数据,只需要建立日志文件目录即可。

 

```js

 

#建立mongos目录

mkdir -p /data/mongodbtest/mongos/log

 

#建立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

 

#建立mongos目录

mkdir -p /data/mongodbtest/mongos/log

 

#建立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

```

5、规划5个组件对应的端口号,由于一个机器需要同时部署、config server 、shard1、shard2、shard3,所以需要用端口进行区分。

这个端口可以自由定义,在本文为,为,为,为22002,为22003.

6、在每一台服务器分别启动配置服务器。

 

```js
 
/data/mongodbtest/mongodb-linux-x86_64-2.4.8/bin/mongod --configsvr --dbpath /data/mongodbtest/config/data --port 21000 --logpath /data/mongodbtest/config/log/config.log --fork
/data/mongodbtest/mongodb-linux-x86_64-2.4.8/bin/mongod --configsvr --dbpath /data/mongodbtest/config/data --port 21000 --logpath /data/mongodbtest/config/log/config.log --fork
```

7、在每一台服务器分别启动mongos服务器。

 

```js
/data/mongodbtest/mongodb-linux-x86_64-2.4.8/bin/mongos  --configdb 192.168.0.136:21000,192.168.0.137:21000,192.168.0.138:21000  --port 20000   --logpath  /data/mongodbtest/mongos/log/mongos.log --fork
 
/data/mongodbtest/mongodb-linux-x86_64-2.4.8/bin/mongos  --configdb 192.168.0.136:21000,192.168.0.137:21000,192.168.0.138:21000  --port 20000   --logpath  /data/mongodbtest/mongos/log/mongos.log --fork
```

8、配置各个分片的副本集。

```js
 
#在每个机器里分别设置分片1服务器及副本集shard1
/data/mongodbtest/mongodb-linux-x86_64-2.4.8/bin/mongod --shardsvr --replSet shard1 --port 22001 --dbpath /data/mongodbtest/shard1/data  --logpath /data/mongodbtest/shard1/log/shard1.log --fork --nojournal  --oplogSize 10
 
#在每个机器里分别设置分片1服务器及副本集shard1
/data/mongodbtest/mongodb-linux-x86_64-2.4.8/bin/mongod --shardsvr --replSet shard1 --port 22001 --dbpath /data/mongodbtest/shard1/data  --logpath /data/mongodbtest/shard1/log/shard1.log --fork --nojournal  --oplogSize 10

为了快速启动并节约测试环境存储空间,这里加上是为了关闭日志信息,在我们的测试环境不需要初始化这么大的redo日志。同样设置是为了降低文件的大小,oplog是一个固定长度的它存在于”local”数据库中,用于记录Replica Sets操作日志。注意,这里的设置是为了测试!

 

#在每个机器里分别设置分片2服务器及副本集shard2
/data/mongodbtest/mongodb-linux-x86_64-2.4.8/bin/mongod --shardsvr --replSet shard2 --port 22002 --dbpath /data/mongodbtest/shard2/data  --logpath /data/mongodbtest/shard2/log/shard2.log --fork --nojournal  --oplogSize 10
 
#在每个机器里分别设置分片2服务器及副本集shard2
/data/mongodbtest/mongodb-linux-x86_64-2.4.8/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/mongodb-linux-x86_64-2.4.8/bin/mongod --shardsvr --replSet shard3 --port 22003 --dbpath /data/mongodbtest/shard3/data  --logpath /data/mongodbtest/shard3/log/shard3.log --fork --nojournal  --oplogSize 10
 
#在每个机器里分别设置分片3服务器及副本集shard3
/data/mongodbtest/mongodb-linux-x86_64-2.4.8/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.0.136,连接mongodb

 

#设置第一个分片副本集
/data/mongodbtest/mongodb-linux-x86_64-2.4.8/bin/mongo  127.0.0.1:22001
 
#使用admin数据库
use admin
 
#定义副本集配置
config = { _id:"shard1", members:[
                     {_id:0,host:"192.168.0.136:22001"},
                     {_id:1,host:"192.168.0.137:22001"},
                     {_id:2,host:"192.168.0.138:22001",arbiterOnly:true}
                ]
         }
 
#初始化副本集配置
rs.initiate(config);
 
#设置第二个分片副本集
/data/mongodbtest/mongodb-linux-x86_64-2.4.8/bin/mongo  127.0.0.1:22002
 
#使用admin数据库
use admin
 
#定义副本集配置
config = { _id:"shard2", members:[
                     {_id:0,host:"192.168.0.136:22002"},
                     {_id:1,host:"192.168.0.137:22002"},
                     {_id:2,host:"192.168.0.138:22002",arbiterOnly:true}
                ]
         }
 
#初始化副本集配置
rs.initiate(config);
 
#设置第三个分片副本集
/data/mongodbtest/mongodb-linux-x86_64-2.4.8/bin/mongo    127.0.0.1:22003
 
#使用admin数据库
use admin
 
#定义副本集配置
config = { _id:"shard3", members:[
                     {_id:0,host:"192.168.0.136:22003"},
                     {_id:1,host:"192.168.0.137:22003"},
                     {_id:2,host:"192.168.0.138:22003",arbiterOnly:true}
                ]
         }
 
#初始化副本集配置
rs.initiate(config);
 
#设置第一个分片副本集
/data/mongodbtest/mongodb-linux-x86_64-2.4.8/bin/mongo  127.0.0.1:22001
 
#使用admin数据库
use admin
 
#定义副本集配置
config = { _id:"shard1", members:[
                     {_id:0,host:"192.168.0.136:22001"},
                     {_id:1,host:"192.168.0.137:22001"},
                     {_id:2,host:"192.168.0.138:22001",arbiterOnly:true}
                ]
         }
 
#初始化副本集配置
rs.initiate(config);
 
#设置第二个分片副本集
/data/mongodbtest/mongodb-linux-x86_64-2.4.8/bin/mongo  127.0.0.1:22002
 
#使用admin数据库
use admin
 
#定义副本集配置
config = { _id:"shard2", members:[
                     {_id:0,host:"192.168.0.136:22002"},
                     {_id:1,host:"192.168.0.137:22002"},
                     {_id:2,host:"192.168.0.138:22002",arbiterOnly:true}
                ]
         }
 
#初始化副本集配置
rs.initiate(config);
 
#设置第三个分片副本集
/data/mongodbtest/mongodb-linux-x86_64-2.4.8/bin/mongo    127.0.0.1:22003
 
#使用admin数据库
use admin
 
#定义副本集配置
config = { _id:"shard3", members:[
                     {_id:0,host:"192.168.0.136:22003"},
                     {_id:1,host:"192.168.0.137:22003"},
                     {_id:2,host:"192.168.0.138:22003",arbiterOnly:true}
                ]
         }
 
#初始化副本集配置
rs.initiate(config);
```

9、目前搭建了mongodb配置服务器、路由服务器,各个分片服务器,不过应用程序连接到路由服务器并不能使用分片机制,还需要在程序里设置分片配置,让分片生效。

 

```js
 
#连接到mongos
/data/mongodbtest/mongodb-linux-x86_64-2.4.8/bin/mongo  127.0.0.1:20000
 
#使用admin数据库
user  admin
 
#串联路由服务器与分配副本集1
db.runCommand( { addshard : "shard1/192.168.0.136:22001,192.168.0.137:22001,192.168.0.138:22001"});
 
#连接到mongos
/data/mongodbtest/mongodb-linux-x86_64-2.4.8/bin/mongo  127.0.0.1:20000
 
#使用admin数据库
user  admin
 
#串联路由服务器与分配副本集1
db.runCommand( { addshard : "shard1/192.168.0.136:22001,192.168.0.137:22001,192.168.0.138:22001"});
如里shard是单台服务器,用这样的命令加入,如果shard是副本集,用db.runCommand( { addshard : “replicaSetName/[:port][,serverhostname2[:port],…]” });这样的格式表示。
 
 
 
#串联路由服务器与分配副本集2
db.runCommand( { addshard : "shard2/192.168.0.136:22002,192.168.0.137:22002,192.168.0.138:22002"});
#串联路由服务器与分配副本集2
db.runCommand( { addshard : "shard2/192.168.0.136:22002,192.168.0.137:22002,192.168.0.138:22002"});
 
 
#串联路由服务器与分配副本集3
db.runCommand( { addshard : "shard3/192.168.0.136:22003,192.168.0.137:22003,192.168.0.138:22003"});
 
#串联路由服务器与分配副本集3
db.runCommand( { addshard : "shard3/192.168.0.136:22003,192.168.0.137:22003,192.168.0.138:22003"});
XHTML
 
#查看分片服务器的配置
db.runCommand( { listshards : 1 } );
 
#查看分片服务器的配置
db.runCommand( { listshards : 1 } );
```
内容输出
 
```js
 
{
         "shards" : [
                {
                        "_id" : "shard1",
                        "host" : "shard1/192.168.0.136:22001,192.168.0.137:22001"
                },
                {
                        "_id" : "shard2",
                        "host" : "shard2/192.168.0.136:22002,192.168.0.137:22002"
                },
                {
                        "_id" : "shard3",
                        "host" : "shard3/192.168.0.136:22003,192.168.0.137:22003"
                }
        ],
        "ok" : 1
}
{
         "shards" : [
                {
                        "_id" : "shard1",
                        "host" : "shard1/192.168.0.136:22001,192.168.0.137:22001"
                },
                {
                        "_id" : "shard2",
                        "host" : "shard2/192.168.0.136:22002,192.168.0.137:22002"
                },
                {
                        "_id" : "shard3",
                        "host" : "shard3/192.168.0.136:22003,192.168.0.137:22003"
                }
        ],
        "ok" : 1
}
```

因为192.168.0.138是每个分片副本集的仲裁节点,所以在上面结果没有列出来。

10、目前配置服务、路由服务、分片服务、副本集服务都已经串联起来了,但我们的目的是希望插入数据,数据能够自动分片,就差那么一点点,一点点。。。连接在mongos上,准备让指定的数据库、指定的集合分片生效。

```js
 
#指定testdb分片生效
db.runCommand( { enablesharding :"testdb"});
 
#指定testdb分片生效
db.runCommand( { enablesharding :"testdb"});
XHTML
 
#指定数据库里需要分片的集合和片键
db.runCommand( { shardcollection : "testdb.table1",key : {id: 1} } )
 
#指定数据库里需要分片的集合和片键
db.runCommand( { shardcollection : "testdb.table1",key : {id: 1} } )
```
我们设置testdb的表需要分片,根据自动分片到,shard2,shard3 上面去。要这样设置是因为不是所有mongodb 的数据库和表都需要分片!
11、测试分片配置结果。
 
```js
#连接mongos服务器
/data/mongodbtest/mongodb-linux-x86_64-2.4.8/bin/mongo  127.0.0.1:20000
 
#连接mongos服务器
/data/mongodbtest/mongodb-linux-x86_64-2.4.8/bin/mongo  127.0.0.1:20000
 
 
#使用testdb
use  testdb;
 
#使用testdb
use  testdb;
 
 
#插入测试数据
for (var i = 1; i <= 100000; i++)
db.table1.save({id:i,"test1":"testval1"});
 
#插入测试数据
for (var i = 1; i <= 100000; i++)
db.table1.save({id:i,"test1":"testval1"});
 
 
#查看分片情况如下,部分无关信息省掉了
db.table1.stats();
 
#查看分片情况如下,部分无关信息省掉了
db.table1.stats();
 
```
```js
 
{
        "sharded" : true,
        "ns" : "testdb.table1",
        "count" : 100000,
        "numExtents" : 13,
        "size" : 5600000,
        "storageSize" : 22372352,
        "totalIndexSize" : 6213760,
        "indexSizes" : {
                "_id_" : 3335808,
                "id_1" : 2877952
        },
        "avgObjSize" : 56,
        "nindexes" : 2,
        "nchunks" : 3,
        "shards" : {
                "shard1" : {
                        "ns" : "testdb.table1",
                        "count" : 42183,
                        "size" : 0,
                        ...
                        "ok" : 1
                },
                "shard2" : {
                        "ns" : "testdb.table1",
                        "count" : 38937,
                        "size" : 2180472,
                        ...
                        "ok" : 1
                },
                "shard3" : {
                        "ns" : "testdb.table1",
                        "count" :18880,
                        "size" : 3419528,
                        ...
                        "ok" : 1
                }
        },
        "ok" : 1
}
 
{
        "sharded" : true,
        "ns" : "testdb.table1",
        "count" : 100000,
        "numExtents" : 13,
        "size" : 5600000,
        "storageSize" : 22372352,
        "totalIndexSize" : 6213760,
        "indexSizes" : {
                "_id_" : 3335808,
                "id_1" : 2877952
        },
        "avgObjSize" : 56,
        "nindexes" : 2,
        "nchunks" : 3,
        "shards" : {
                "shard1" : {
                        "ns" : "testdb.table1",
                        "count" : 42183,
                        "size" : 0,
                        ...
                        "ok" : 1
                },
                "shard2" : {
                        "ns" : "testdb.table1",
                        "count" : 38937,
                        "size" : 2180472,
                        ...
                        "ok" : 1
                },
                "shard3" : {
                        "ns" : "testdb.table1",
                        "count" :18880,
                        "size" : 3419528,
                        ...
                        "ok" : 1
                }
        },
        "ok" : 1
}
```

可以看到数据分到3个分片,各自分片数量为:,shard2 “count” : 38937,shard3 “count” : 18880。已经成功了!不过分的好像不是很均匀,所以这个分片还是很有讲究的,后续再深入讨论。

12、java程序调用分片集群,因为我们配置了三个mongos作为入口,就算其中哪个入口挂掉了都没关系,使用集群客户端程序如下:

 

```js
public class TestMongoDBShards {
 
       public static void main(String[] args) {
 
             try {
                  List<ServerAddress> addresses = new ArrayList<ServerAddress>();
                  ServerAddress address1 = new ServerAddress("192.168.0.136" , 20000);
                  ServerAddress address2 = new ServerAddress("192.168.0.137" , 20000);
                  ServerAddress address3 = new ServerAddress("192.168.0.138" , 20000);
                  addresses.add(address1);
                  addresses.add(address2);
                  addresses.add(address3);
 
                  MongoClient client = new MongoClient(addresses);
                  DB db = client.getDB( "testdb" );
                  DBCollection coll = db.getCollection( "table1" );
 
                  BasicDBObject object = new BasicDBObject();
                  object.append( "id" , 1);
 
                  DBObject dbObject = coll.findOne(object);
 
                  System. out .println(dbObject);
 
            } catch (Exception e) {
                  e.printStackTrace();
            }
      }
}
 
public class TestMongoDBShards {
 
       public static void main(String[] args) {
 
             try {
                  List<ServerAddress> addresses = new ArrayList<ServerAddress>();
                  ServerAddress address1 = new ServerAddress("192.168.0.136" , 20000);
                  ServerAddress address2 = new ServerAddress("192.168.0.137" , 20000);
                  ServerAddress address3 = new ServerAddress("192.168.0.138" , 20000);
                  addresses.add(address1);
                  addresses.add(address2);
                  addresses.add(address3);
 
                  MongoClient client = new MongoClient(addresses);
                  DB db = client.getDB( "testdb" );
                  DBCollection coll = db.getCollection( "table1" );
 
                  BasicDBObject object = new BasicDBObject();
                  object.append( "id" , 1);
 
                  DBObject dbObject = coll.findOne(object);
 
                  System. out .println(dbObject);
 
            } catch (Exception e) {
                  e.printStackTrace();
            }
      }
}
 
```

整个分片集群搭建完了,思考一下我们这个架构是不是足够好呢?其实还有很多地方需要优化,比如我们把所有的仲裁节点放在一台机器,其余两台机器承担了全部读写操作,但是作为仲裁的192.168.0.138相当空闲。让机器3 192.168.0.138多分担点责任吧!架构可以这样调整,把机器的负载分的更加均衡一点,每个机器既可以作为主节点、副本节点、仲裁节点,这样压力就会均衡很多了,如图

 

![分片](fenpianzuiyou.jpg)

 

缺点:只有真的是大数据,Sharding才能显现威力,Sharding可以将多片数据集中到路由节点上进行一些对比,然后将数据返回给客户端,但是效率还是比较低的说。

### Master-Slaver

这个是最简答的集群搭建,不过准确说也不能算是集群,只能说是主备。并且官方已经不推荐这种方式,所以在这里只是简单的介绍下吧,搭建方式也相对简单。

```js
./mongod --master --dbpath /data/masterdb/      #主节点  
  
./mongod --slave --source <masterip:masterport> --dbpath /data/slavedb/     备节点

```

基本上只要在主节点和备节点上分别执行这两条命令,Master-Slaver就算搭建完成了。我没有试过主节点挂掉后备节点是否能变成主节点,不过既然已经不推荐了,大家就没必要去使用了。