副本集相关:

1.搭建副本集。

(1)为副本集中的副本配置以下参数(这些参数必须配置的),之后重启副本。

  replSet=rs0         # 副本的名称

  oplogSize=1024     # oplog的初始大小

  keyFile=/home/mongodb261/data38017/mongodb-keyfile  #  keyfile文件的路径,用户副本之间通信。

 

(2)登陆primary,初始化副本。

 rsconf={"_id":"rs0","members":[{"_id":0,"host":"10.0.26.90:38017"}]}

 rs.initiate(rsconf)  

然后执行rs.status()查看副本集状态。

rs0:PRIMARY> rs.status()

{

        "set" : "rs0",

        "date" : ISODate("2015-03-03T08:23:02Z"),

        "myState" : 1,

        "members" : [

                {

                        "_id" : 0,

                        "name" : "10.0.26.90:38017",

                        "health" : 1,

                        "state" : 1,

                        "stateStr" : "PRIMARY",

                        "uptime" : 2063,

                        "optime" : Timestamp(1425370976, 1),

                        "optimeDate" : ISODate("2015-03-03T08:22:56Z"),

                        "electionTime" : Timestamp(1425368972, 1),

                        "electionDate" : ISODate("2015-03-03T07:49:32Z"),

                        "self" : true

                }

        ],

        "ok" : 1

}

stateStr:这个字段为primary 表明初始化成功。

现在的副本集中只有一个主库,所以需要添加副本。

 

Note:keyFile文件必须是同一个文件,可以使用方法生成一个keyfile,然后cp到其他服务器中。

cd /mnt/mongodb/rs/config  

openssl rand -base64 741 > mongodb-keyfile  

chmod 300 mongodb-keyfile  

 

 

 

(3)添加副本

rs0:PRIMARY> rs.add("10.0.26.90:38018")

{ "ok" : 1 }

rs0:PRIMARY> rs.status()

{

        "set" : "rs0",

        "date" : ISODate("2015-03-03T08:27:55Z"),

        "myState" : 1,

        "members" : [

                {

                        "_id" : 0,

                        "name" : "10.0.26.90:38017",

                        "health" : 1,

                        "state" : 1,

                        "stateStr" : "PRIMARY",

                        "uptime" : 2356,

                        "optime" : Timestamp(1425371234, 1),

                        "optimeDate" : ISODate("2015-03-03T08:27:14Z"),

                        "electionTime" : Timestamp(1425368972, 1),

                        "electionDate" : ISODate("2015-03-03T07:49:32Z"),

                        "self" : true

                },

                {

                        "_id" : 1,

                        "name" : "10.0.26.90:38018",

                        "health" : 1,

                        "state" : 2,

                        "stateStr" : "SECONDARY",

                        "uptime" : 41,

                        "optime" : Timestamp(1425371234, 1),

                        "optimeDate" : ISODate("2015-03-03T08:27:14Z"),

                        "lastHeartbeat" : ISODate("2015-03-03T08:27:54Z"),

                        "lastHeartbeatRecv" : ISODate("2015-03-03T08:27:53Z"),

                        "pingMs" : 0,

                        "syncingTo" : "10.0.26.90:38017"

                }

        ],

        "ok" : 1

}

 

rs.status() 的输出结果中可以看到10.0.26.90:38018 已经添加到副本集中。

 

2.副本集的维护

 <1>.添加节点(仲裁/数据)/删除节点

添加数据节点:rs.add("10.0.26.90:38019") 

添加仲裁节点:rs.add({"_id":2,"host":"10.0.26.90:38020","arbiterOnly":"true"})

rs.addArb("10.0.26.90:38020") 也可以添加仲裁服务器

rs0:PRIMARY> rs.status()

{

        "set" : "rs0",

        "date" : ISODate("2015-03-03T08:54:08Z"),

        "myState" : 1,

        "members" : [

                {

                        "_id" : 0,

                        "name" : "10.0.26.90:38017",

                        "health" : 1,

                        "state" : 1,

                        "stateStr" : "PRIMARY",

                        "uptime" : 3929,

                        "optime" : Timestamp(1425372216, 1),

                        "optimeDate" : ISODate("2015-03-03T08:43:36Z"),

                        "electionTime" : Timestamp(1425368972, 1),

                        "electionDate" : ISODate("2015-03-03T07:49:32Z"),

                        "self" : true

                },

                {

                        "_id" : 1,

                        "name" : "10.0.26.90:38018",

                        "health" : 1,

                        "state" : 2,

                        "stateStr" : "SECONDARY",

                        "uptime" : 649,

                        "optime" : Timestamp(1425372216, 1),

                        "optimeDate" : ISODate("2015-03-03T08:43:36Z"),

                        "lastHeartbeat" : ISODate("2015-03-03T08:54:06Z"),

                        "lastHeartbeatRecv" : ISODate("2015-03-03T08:54:07Z"),

                        "pingMs" : 0,

                        "syncingTo" : "10.0.26.90:38017"

                },

                {

                        "_id" : 2,

                        "name" : "10.0.26.90:38019",

                        "health" : 1,

                        "state" : 2,

                        "stateStr" : "SECONDARY",

                        "uptime" : 649,

                        "optime" : Timestamp(1425372216, 1),

                        "optimeDate" : ISODate("2015-03-03T08:43:36Z"),

                        "lastHeartbeat" : ISODate("2015-03-03T08:54:08Z"),

                        "lastHeartbeatRecv" : ISODate("2015-03-03T08:54:06Z"),

                        "pingMs" : 0,

                        "syncingTo" : "10.0.26.90:38017"

                },

                {

                        "_id" : 10,

                        "name" : "10.0.26.90:38020",

                        "health" : 1,

                        "state" : 7,

                        "stateStr" : "ARBITER",

                        "uptime" : 3,

                        "lastHeartbeat" : ISODate("2015-03-03T08:54:07Z"),

                        "lastHeartbeatRecv" : ISODate("2015-03-03T08:54:07Z"),

                        "pingMs" : 8

                }

        ],

        "ok" : 1

}

从状态可以看出数据节点10.0.26.90:38019 ,仲裁节点10.0.26.90:38020都已经成功

 

(2)手动指定primary(设置优先级并且重新加载配置文件)

cfg=rs.conf()    

cfg.members[0].priority=6  #对需要提升为primary的副本甚至更高的priority

rs.reconfig(cfg)   # 重新加载配置,强制重新选举

 

以下示例是将10.0.26.90:38018设置为primary

rs0:PRIMARY> cfg=rs.conf()

{

        "_id" : "rs0",

        "version" : 46,

        "members" : [

                {

                        "_id" : 0,

                        "host" : "10.0.26.90:38017",

                        "priority" : 6

                },

                {

                        "_id" : 1,

                        "host" : "10.0.26.90:38018",

                        "priority" : 6

                },

                {

                        "_id" : 2,

                        "host" : "10.0.26.90:38019"

                },

                {

                        "_id" : 10,

                        "host" : "10.0.26.90:38020",

                        "arbiterOnly" : true

                }

        ]

}

rs0:PRIMARY>  cfg.members[1].priority=10

10

rs0:PRIMARY> rs.reconfig(cfg)

2015-03-03T01:20:36.680-0800 DBClientCursor::init call() failed

2015-03-03T01:20:36.696-0800 trying reconnect to 10.0.26.90:38017 (10.0.26.90) failed

2015-03-03T01:20:36.698-0800 reconnect 10.0.26.90:38017 (10.0.26.90) ok

reconnected to server after rs command (which is normal)

rs0:SECONDARY> rs.status()

{

        "set" : "rs0",

        "date" : ISODate("2015-03-03T09:20:46Z"),

        "myState" : 2,

        "syncingTo" : "10.0.26.90:38018",

        "members" : [

                {

                        "_id" : 0,

                        "name" : "10.0.26.90:38017",

                        "health" : 1,

                        "state" : 2,

                        "stateStr" : "SECONDARY",

                        "uptime" : 5527,

                        "optime" : Timestamp(1425374436, 1),

                        "optimeDate" : ISODate("2015-03-03T09:20:36Z"),

                        "infoMessage" : "syncing to: 10.0.26.90:38018",

                        "self" : true

                },

                {

                        "_id" : 1,

                        "name" : "10.0.26.90:38018",

                        "health" : 1,

                        "state" : 1,

                        "stateStr" : "PRIMARY",

                        "uptime" : 10,

                        "optime" : Timestamp(1425374436, 1),

                        "optimeDate" : ISODate("2015-03-03T09:20:36Z"),

                        "lastHeartbeat" : ISODate("2015-03-03T09:20:44Z"),

                        "lastHeartbeatRecv" : ISODate("2015-03-03T09:20:45Z"),

                        "pingMs" : 1,

                        "electionTime" : Timestamp(1425374442, 1),

                        "electionDate" : ISODate("2015-03-03T09:20:42Z")

                },

                {

                        "_id" : 2,

                        "name" : "10.0.26.90:38019",

                        "health" : 1,

                        "state" : 2,

                        "stateStr" : "SECONDARY",

                        "uptime" : 10,

                        "optime" : Timestamp(1425374436, 1),

                        "optimeDate" : ISODate("2015-03-03T09:20:36Z"),

                        "lastHeartbeat" : ISODate("2015-03-03T09:20:44Z"),

                        "lastHeartbeatRecv" : ISODate("2015-03-03T09:20:44Z"),

                        "pingMs" : 1,

                        "lastHeartbeatMessage" : "syncing to: 10.0.26.90:38018",

                        "syncingTo" : "10.0.26.90:38018"

                },

                {

                        "_id" : 10,

                        "name" : "10.0.26.90:38020",

                        "health" : 1,

                        "state" : 7,

                        "stateStr" : "ARBITER",

                        "uptime" : 10,

                        "lastHeartbeat" : ISODate("2015-03-03T09:20:46Z"),

                        "lastHeartbeatRecv" : ISODate("2015-03-03T09:20:45Z"),

                        "pingMs" : 0

                }

        ],

        "ok" : 1

}

 

从状态中可以看出10.0.26.90:38018 已经是primary 了 

 

 

(3)设置副本可读

有两种方法可以使副本可读。

方法一:在需要读的服务器上执行以下脚本

db.getMongo().setSlaveOk();

但是这个方法具有易失性(副本重启又变成不可读了)

方法二:在副本中找到.mongorc.js文件(这是一个隐藏文件),在这个文件中添加一下命令

rs.slaveOk() .这个方法永久有效。

 

 

(4).快速添加一个副本集(以备份的方式添加副本集,或是直接cp文件)

方法一:从副本集中分离出一个副本A,将即将添加的副本B中的数据目录清空,

A的数据目录文件复制到B的数据目录中,然后重启副本B的服务。

最后以此将副本A,和副本B添加至副本集中(该方法已经验证过).

 

方法二:mongodump/mongorestore的方式备份还原初始化副本.

#使用--oplog方式备份一个副本,产生一个日志文件(oplog.bson)

mongodump --host=10.0.26.90 --port=38018 --username=root  --password=anyu@2014  --authenticationDatabase=admin --out=/home/bckup/backup_all --oplog 

#使用--oplogReplay 还原一个备份(应用oplog.bson)

mongorestore --host=10.0.26.90 --port=38019 --username=root --password=anyu@2014   /home/bckup/backup_all  --oplogReplay --drop  

#local 库中如果没有oplog.rs集合就手动创建一个。

use local

db.createCollection("oplog.rs", {"capped" : true, "size" : 10000000})

#oplog.bson记录还原到oplog.rs中。

mongorestore  --host=10.0.26.90 --port=38019 --authenticationDatabase=admin --username=root --password=anyu@2014 -d local -c oplog.rs /home/bckup/backup_all/oplog.bson

 

参看链接http://my.oschina.net/169/blog/158976

 

 

(5)副本的几种状态解释

startup:加载副本集配置。之后进入startup2

startup2:副本创建几个线程,用于处理复制和选举(在初始化副本时会比较常见这种状态)

recovering:副本运行正常,但不能处理一些请求。

ARBITER:在正常情况下,仲裁者始终处于这个状态。

down/unkown:处于次状态下副本无法和其他副本通信(有可能副本挂掉了,也有可能网络故障).

remove:被移除的成员会处于这个状态,

rollback:副本正在进行数据回滚.

fatal:副本遇到致命的错误,一般情况只能重新同步副本.

Primary:主库的正常状态(可对完提供服务)

Secondary:从库的正常状态(可对外提供服务)

 

 

(6)rs.status()输出解读

health:表示是否服务器可达,可达是1,不可达是0

state:副本状态,数值表示(1:primary,2:secondary,7:ARBITER)

stateStr:副本状态(primary,secondary,reconvering)

uptime:副本不间断可达经过的时间,单位是秒。

self:这个信息出现在执行rs.status()函数的成员信息中

pingMs:心跳从当前服务器达到某个成员所花费的平均时间

health:表示是否服务器可达,可达是1,不可达是0

syncingTo:表示当前服务器从哪个节点在做同步。

lastHeartbeat:当前服务器最后一次收到其他成员心跳的时间

electionDate/electionTime:选举时间

optimeoptimeDate表达的信息也是一样的,只是表示的方式不同,一个是用新纪元开始的毫秒数表示的,

一个是用一种更容易阅读的方式表示。

Errmsg:成员在心跳请求中返回的状态信息,通过是一些状态信息,不全是错误信息。

 

 

(7)调整oplog的大小。

<1>.关闭当前服务器

<2>.修改配置文件,使其以单机模式运行。

<3>.oplog.rs中的最后一条记录保存到其他集合中

var lastlog=db.oplog.rs.find().sort({ts:-1}).limit(1)

#这个语句也可以获得最后的oplog,而且更快db.oplog.rs.find().sort({$natural:-1}).limit(1)

db.temp.save(lastlog.next()) 

db.temp.find() //确认是否插入成功

<4>.删除oplog.rs集合

db.oplog.rs.drop()

<5>.创建oplog.rs集合

db.createCollection("oplog.rs",{capped:true,size:1073741824})

<6>.temp中的记录插入oplog.rs,并且确认插入是否成功

var tt=db.temp.find() ;

db.oplog.rs.insert(tt.next()) ;

db.oplog.rs.find();

<7>.添加至副本集中,修改配置,重启服务

 

(8).常用维护命令:

rs.stepDown():primary上执行,使primary退位。

rs.freeze(1200):将每个不想让它成为primary 的机器让它在1200 秒内无法成为primary(这步也可以不做

 

 

(9)副本配置选项:

priority=0:禁止副本成为主结点(优先级为0的结点永远都不会成为主节点)

slaveDelay:延迟备份结点(要求的成员的优先级为0,最好设置为隐藏)

hidden:true(将结点设置为隐藏,客服端无法将读请求发送给它),可以使用rs.isMaster()验证

buildIndexes:false(禁止在备份节点上创建索引)

votes:禁止副本投票(消除副本的投票权)

禁止副本选举(priority=0,votes=0):取消副本的选举和被选举权

 

通过以下方式配置:

cfg=rs.conf()    

cfg.members[1].votes=0

rs.reconfig(cfg)   

 

 

(10)一些比较重要的概念:

选举机制(选举必须满足一下条件)

(1)自身是否能于主结点连通

(2)希望被选举为主节点的备份结点的数据是否最新.

(3)有没有其他更高优先级的成员可以被选举为主节点.

仲裁服务器:当故障出现的时候,确保有一部分服务器满足"大多数".只有当集群中的服务器数量为偶数时才有必要添加仲裁服务器。

优先级:表示一个成员渴望成为主节点的程度。

大多数:只有得到副本集中一半以上的支持才能被选举为primary

 

(11)初始化同步:

(1).找一个同步源(副本集中的任意可用副本)并且删除所有已存在的DB(local除外)

(2).克隆DB(复制数据,数据复制过程中最耗时的部分).

(3).将克隆过程中的所有操作都记录到oplog(oplog第一步)

(4).将第一个oplog同步中的操作记录下来,(感觉有问题)(oplog第二步)

(5).数据复制完毕,开始创建索引。

(6).将创建索引期间的所有操作全部同步过来。(oplog第三步)

(7).完成初始化状态,切换到普通状态。

 

(12)副本集中创建索引:

1.关闭一个节点服务器

2.当机模式运行这个服务器

3.在单机模式下创建索引.

4.将节点作为副本集成员重新启动

5.依次对副本集中的其他副本进行同样操作。

6.最后在primary上创建索引(primary上的索引创建完成后,其他副本同样会复制创建索引的操作,

但是副本已经创建了相同的索引,实际上不会应用该操作.)



 

副本集的搭建相关参考:

http://sunnyyu.blog.51cto.com/8745931/1397878

http://tcrct.iteye.com/blog/2108099

副本集维护相关参考:

http://blog.jobbole.com/72636/

http://www.it165.net/database/html/201402/5280.html

http://snoopyxdy.blog.163.com/blog/static/60117440201241694254441/