副本集相关:
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:选举时间
optime与optimeDate表达的信息也是一样的,只是表示的方式不同,一个是用新纪元开始的毫秒数表示的,
一个是用一种更容易阅读的方式表示。
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/