首页 > 代码库 > mongoDB主从和副本集群配置

mongoDB主从和副本集群配置

mongoDB主从和副本集群配置

Mongodb是时下流行的NoSql数据库(MongoDB是一个基于分布式文件存储的数据库),它的存储方式是文档式存储,并不是Key-Value形式。

 

优势:

快速!(当然,这和具体的应用方式有关,通常来说,它比一般的关系型数据库快5位左右。)

很高的可扩展性轻轻松松就可实现PB级的存储(但是可能我们并不需要PB级的存储,10TB可能就够了)

他有一个很好的 replication 模式 (replica sets)

有很完善的Java API

他的存储格式是Json的,这对Java来说非常好处理,对javascirpt亦然。

运维起来非常方便,你不用专门为它安排一个管理员。

它有一个非常活跃的社区(我提出的一个bug20分钟内就能得到修复。多谢Elliot)

他的版本控制非常清楚。

MongoDB 背后的公司(10gen)已经准备好了明天在 MongoDB 上面的投入的资金了。

劣势

应用经验缺乏,我们都没有相关NoSQL 产品的使用经验。

项目相对来说还比较新。

和以往的存储相比,数据的关系性操作不再存在。

 

 

版本历史

时间

版本

说明

编写者

2014-07-25

1.0

mondoDB主从和副本集群配置

csc

2014-11-5

1.1

mondoDB主从和副本集群配置-修改

csc









 

 

 

 

 

一、配置mongoDB主从集群

 

 

1、介绍:

 

服务器资源有限,主从服务 都部署在一台服务器上面,开启不同的端口运行。

该集群优点:master 读写,slave  读 可以减轻master 的压力,数据做冗余备份

缺点: 主master挂了之后,服务不能自动切换到从slave,存在单点故障

 

mv mongodb-linux-x86_64-1.6.5.tgz /usr/local/

cd /usr/local/

tar -xvzf mongodb-linux-x86_64-1.6.5.tgz

 

2、配置master 服务:

cp -r  mongodb-linux-x86_64-1.6.5  mongodb-01

mkdir  -p /usr/local/mongodb-01/data/master

 

#/usr/local/mongodb-01/bin/mongod--dbpath=/usr/local/mongodb-01/data/master --port=10000--master --logpath=/usr/local/mongodb-01/data/mongodb.log --rest &

 

或者写入配置文档master.conf:

1.  port = 27017  

2.  dbpath = /data/db  

3.  logpath = /var/log/mongodb.log  

4.  logappend = true   

5.  journal = true  

6.  pidfile = /var/run/mongodb.pid  

7.  fork = true  

8.  master = true 

9.   

10.  启动方式:./mongod -f master.conf

11.   

12.  关闭方式

13.    ./ mongod--shutdown  -f master.conf

14.   

15.   

 

 

启动后测试是否正常运行:

#/usr/local/mongodb-01/bin/mongo 127.0.0.1:10000

MongoDB shell version: 1.6.5

connecting to: 127.0.0.1:10000/test

> show dbs;

admin

local

 

3、配置slave 服务:

cp -r  mongodb-linux-x86_64-1.6.5  mongodb-02

mkdir  -p /usr/local/mongodb-01/data/slave

/usr/local/mongodb-02/bin/mongod--dbpath=/usr/local/mongodb-02/data/slave --port=10001--slave --source=localhost:10000 --logpath=/usr/local/mongodb-02/data/mongodb.log--rest

 

或者写入配置文档(slave.conf):

1.  port=27017  

2.  dbpath = /data/db  

3.  logpath = /var/log/mongodb.log  

4.  logappend = true   

5.  journal = true  

6.  fork = true  

7.  slave = true  

8.  source = 10.11.20.140:27017  

9.   

10.  启动方式:./mongod -f master.conf

11.   

 

启动后测试是否正常运行:

#/usr/local/mongodb-02/bin/mongo 127.0.0.1:10001

MongoDB shell version: 1.6.5

connecting to: 127.0.0.1:10001/test

> show dbs;

admin

local

 

4、测试主从功能:

登入 slave 创建表:

 

创建一个“myTest”的数据库,

先运行use myTest命令,之后就做一些操作(如:db.createCollection(‘user‘)),这样就可以创建一个名叫“myTest”的数据库。

 

在从服务上面创建数据库myTest;

/usr/local/mongodb-02/bin/mongo 127.0.0.1:10001

> use mytest

switched to db mytest

> db.createCollection(‘user‘)

{ "errmsg" : "not master", "ok" :0 }

报错信息显示该服务不是主服务,不能插入数据。

但是能查询数据:

> show dbs;

admin

local

 

在主服务上面创建数据库myTest

/usr/local/mongodb-01/bin/mongo 127.0.0.1:10000

> use mytest

switched to db mytest

> db.createCollection(‘user‘)

{ "ok" : 1 }

 

从服务器查询数据库,看是否该库同步过来。如果从服务器没有查询到该库,则检查服务的正确性。

> show dbs;

admin

local

myTest

test

 

 

 

查询数据库状态:

 

> db.version();

1.6.5

 

> db.stats();

{

       "collections" : 3,

       "objects" : 4,

       "avgObjSize" : 51,

       "dataSize" : 204,

       "storageSize" : 16384,

       "numExtents" : 3,

       "indexes" : 1,

       "indexSize" : 8192,

       "fileSize" : 201326592,

        "ok" : 1

}

 

查看当前db的链接机器地址

> db.getMongo();

connection to 127.0.0.1:10000

 

创建用户

> db.addUser(‘names‘);

{

        "user" :"names",

       "readOnly" : false,

        "pwd" :"29cdbdd1255032d35e099aa7ebf8c3f9"

}

查看用户

> show users;

{

        "_id" :ObjectId("53d0bcfaafa6df02ce900daf"),

        "user" :"names",

       "readOnly" : false,

        "pwd" :"29cdbdd1255032d35e099aa7ebf8c3f9"

}

 

查看数据

db.test_1.find();

创建数据:

db.test_1.save({id:1}); 

 

创建新的数据库

  我们通过使用“use new-databasename”的语法去使用一个新的数据库,注意,即使你的数据库还没建立起来,依然可以这样使用,因为mongodb会在真正插入了数据后,才会真正建立起来。

   >use mkyongdb

   switched to db mkyongdb

   > show dbs

   admin   0.03125GB

   local   (empty)

  注意,在use mkyongdb后,mkyongdb实际上还没真正建立起来,只是表明目前是在使用mkyongdb了。

保存数据

  定义一个collection,名为“users”,然后插入数据,如下:

   db.users.save({username:"mkyong"} )

    db.users.find()

  { "_id" : ObjectId("4dbac7bfea37068bd0987573"),"username" : "mkyong" }

     db.users.count();

    1

    show dbs

  admin   0.03125GB

  local   (empty)

  mkyongdb        0.03125GB

 

 

关闭mongoDB

 [root@test2 bin]# ./mongod --shutdown -f../data/slaver.conf

不推荐用kill方法杀掉进程

杀掉之后,如果要重启,请先删除掉 *.pid  文件

二、配置mongoDB  ReplicaSet (副本集)

集群当中包含了多份数据,保证主节点挂掉了,备节点能继续提供数据服务,提供的前提就是数据需要和主节点一致。如下图:

spacer.gif

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

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

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

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

 

1.建立数据文件夹

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

[plain] viewplaincopy

10.10.148.130   mkdir -p /mongodb/data/master   

10.10.148.131 mkdir -p /mongodb/data/slaver   

10.10.148.132   mkdir -p /mongodb/data/arbiter    

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

2.建立配置文件

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

10.10.148.130 master 服务器配置:

[plain] viewplaincopy

#master.conf  

dbpath=/mongodb/data/master  

logpath=/mongodb/log/master.log  

pidfilepath=/mongodb/master.pid  

directoryperdb=true  

logappend=true  

replSet=testrs  

bind_ip=10.10.148.130  

port=27017  

oplogSize=10000  

fork=true  

noprealloc=true  

 

[plain] viewplaincopy

10.10.148.131slaver服务器配置:

#slaver.conf  

dbpath=/mongodb/data/slaver  

logpath=/mongodb/log/slaver.log  

pidfilepath=/mongodb/slaver.pid  

directoryperdb=true  

logappend=true  

replSet=testrs  

bind_ip=10.10.148.131  

port=27017  

oplogSize=10000  

fork=true  

noprealloc=true  

 

 

[plain] viewplaincopy

10.10.148.132arbiter服务器配置:

 

#arbiter.conf  

dbpath=/mongodb/data/arbiter  

logpath=/mongodb/log/arbiter.log  

pidfilepath=/mongodb/arbiter.pid  

directoryperdb=true  

logappend=true  

replSet=testrs  

bind_ip=10.10.148.132  

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目录下

[java] viewplaincopy

./monood -f master.conf  

./mongod -f slaver.conf  

./mongod -f arbiter.conf  

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

如果要开启图形界面管理,则后面加上 --rest 启动

如:

./monood -f master.conf --rest

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

方法一:  添加节点时候,同时设置优先级,指定节点类型

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

随便在一个终端进行,这个终端会被当成primary节点,但是需要把该终端的优先级设置高。

priority 数字越大,优先级越高

 [plain] view plaincopy

./mongo 10.10.148.130:27017   #ip和port是某个节点的地址  

>use admin  

>cfg={ _id:"testrs", members:[ {_id:0,host:‘10.10.148.130:27017‘,priority:2}, {_id:1,host:‘10.10.148.131:27017‘,priority:1},   

{_id:2,host:‘10.10.148.132:27017‘,arbiterOnly:true}] };  

>rs.initiate(cfg)             #使配置生效  

 

方法二:只添加节点,后期设置或者更改优先级和节点类型(不做介绍)

#####################以下可忽略#################################

版本为:2.4.3 按照上诉方法设置通过。

版本为:1.76 的设置过程会报错:

errmsg" : "couldn‘t parse cfgobject bad config for member[0] this version of mongod only supports priorities0 and 1",

配置的时候报错,只支持0跟1 的优先级

随便在一个终端进行,这个终端会被当成primary节点,因此连接的这个终端priority优先级要设置高,如果设置成 priority:0  ,primary节点会报错:

备注:Priority0的节点永远不能成为主节点,所以设置Secondary-only节点只需要将其priority设置为0.

 

errmsg" : "couldn‘t initiate :initiation and reconfiguration of a replica set must be sent to a node that canbecome primary",

 

 

>cfg={_id:"testrs", members:[ {_id:0,host:‘127.0.0.1:10001‘,priority:1},{_id:1,host:‘127.0.0.1:10002‘,priority:0},{_id:2,host:‘127.0.0.1:10003‘,arbiterOnly:true}] };

>rs.initiate(cfg)             #使配置生效  

############################################################################

 

 

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

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

[plain] viewplaincopy

{  

        "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  

}  

如果配置正在生效,其中会包含如下信息:

[plain] viewplaincopy

"stateStr" : "RECOVERING"  


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

5.备注--笔记:      

1增节点到副本中。

新增加一台服务加入到副本集中:

rs.add(‘192.168.200.25:27017‘)

 

加入后,执行,rs.status(); 显示:"errmsg" : "initial sync pending"  显示初始化过程中,一会儿后正常。

2删除副本中的节点:

rs.remove(‘192.168.200.25:27017‘)

3查看副本集的状态

rs.status()

db.isMaster();    查看主备(从)节点的状态

 

4.操作Secondary

默认情况下,Secondary是不提供服务的,即不能读和写。会提示:
error: { ‘$err‘ : ‘not master and slaveOk=false‘, ‘code‘ : 13435 }

在特殊情况下需要读的话则需要执行命令:
rs.slaveOk()
,只对当前连接有效。

 

 

5.关闭节点命令

051.mmm:PRIMARY> use admin

052.switched to db admin

053.mmm:PRIMARY> db.shutdownServer()

054. 

或者见目录一关闭mongodb

6.备注、仲裁节点

所有的Secondary都宕机、或则副本集中只剩下一个节点,则该节点只能为Secondary节点,也就意味着整个集群智能进行读操作而不能进行写操作,当其他的恢复时,之前的primary节点仍然是primary节点。

当某个节点宕机后重新启动该节点会有一段的时间(时间长短视集群的数据量和宕机时间而定)导致整个集群中所有节点都成为secondary而无法进行写操作(如果应用程序没有设置相应的ReadReference也可能不能进行读取操作)。

官方推荐的最小的副本集也应该具备一个primary节点和两个secondary节点,或者1primary节点和1secondary节点,加上一个arbiter节点。两个节点的副本集不具备真正的故障转移能力。

1 primary+2 secondary 或者1 primary + 1secondary + 1 arbiter

 

使用仲裁者主要是因为MongoDB副本集需要奇数成员,而又没有足够服务器的情况。

在服务器充足的情况下,不应该使用仲裁者节点

 

 

4 更改节点优先级(by网络)

 

修改节点的优先级可以触发重新选举,这样可以人工指定主节点。
使用如下命令,在主节点登录,将192.168.1.3提升为Master。
rs.conf();
cfg=rs.conf();
cfg.members[0].priority=1
cfg.members[1].priority=1
cfg.members[2].priority=10
rs.reconfig(cfg);
需要注意的是,修改节点优先级需要登录Master节点运行。否则报错。
http://blog.itpub.net/attachment/201406/5/29254281_1401973884i3T3.jpg

再次查看集群状态,可以看到192.168.1.3已经作为Master运行

 

7 副本集成员状态(by网络)

 

副本集成员状态指的是rs.status()stateStr字段
http://blog.itpub.net/attachment/201406/5/29254281_1401974456AFRz.jpg
STARTUP
:刚加入到复制集中,配置还未加载

STARTUP2
:配置已加载完,初始化状态

RECOVERING
:正在恢复,不适用读

ARBITER:
仲裁者

DOWN
:节点不可到达

UNKNOWN
:未获取其他节点状态而不知是什么状态,一般发生在只有两个成员的架构,脑裂

REMOVED
:移除复制集

ROLLBACK
:数据回滚,在回滚结束时,转移到RECOVERINGSECONDARY状态

FATAL
:出错。查看日志grepreplSetFATAL”找出错原因,重新做同步

PRIMARY
:主节点

SECONDARY
:备份节点

 

 

12 读写分离 by(网络)

如果Master节点读写压力过大,可以考虑读写分离的方案。

http://blog.itpub.net/attachment/201406/5/29254281_1401974524GG2F.jpg

 



不过需要考虑一种场景,就是主服务器的写入压力非常的大,所以副本节点复制的写入压力同样很大。
这时副本节点如果读取压力也很大的话,根据MongoDB库级别读写锁的机制,
很可能复制写入程序拿不到写锁,从而导致副本节点与主节点有较大延迟。

如果进行读写分离,首先需要在副本节点声明其为slave,
http://blog.itpub.net/attachment/201406/5/29254281_1401974588Xnj3.jpg
然后在JAVA程序中进行设置
http://blog.itpub.net/attachment/201406/5/29254281_1401974737H1Hj.jpg
其中的ReadRreference有几种设置,

 

http://blog.itpub.net/attachment/201406/5/29254281_1401974782ubqo.jpg
primary:默认参数,只从主节点上进行读取操作;

primaryPreferred:大部分从主节点上读取数据,只有主节点不可用时从secondary节点读取数据。

secondary:只从secondary节点上进行读取操作,存在的问题是secondary节点的数据会比primary节点数据“旧”。

secondaryPreferred:优先从secondary节点进行读取操作,secondary节点不可用时从主节点读取数据;

nearest:不管是主节点、secondary节点,从网络延迟最低的节点上读取数据。

参考:

 

6.使用Web控制台,Web端口为28017

Mongodb自带了Web控制台,默认和数据服务一同开启。他的端口在Mongodb数据库服务器端口的基础上加1000,如果是默认的Mongodb数据服务端口(Which is 27017),则相应的Web端口为28017

我的控制台测试:

spacer.gif

 

点击 Replica set status 报错:REST is not enableduse --rest turn on

解决方式:

启动的时候加上 --rest

./monood -f master.conf  --rest

 ./mongod -f slaver.conf  --rest

就可以看到Replica set status 界面了

spacer.gif

 

 


本文出自 “笨鸟先飞” 博客,请务必保留此出处http://2574526.blog.51cto.com/2564526/1572135

mongoDB主从和副本集群配置