mongodb-03 副本集
MongoDB副本集的角色

副本集中数据同步过程
Primary节点写入数据,Secondary通过读取Primary的oplog得到复制信息,开始复制数据并且将复制信息写入到自己的oplog。
如果某个操作失败,则备份节点停止从当前数据源复制数据。
如果某个备份节点由于某些原因挂掉了,当重新启动后,就会自动从oplog的最后一个操作开始同步,同步完成后,将信息写入自己的oplog。
由于复制操作是先复制数据,复制完成后再写入oplog,有可能相同的操作会同步两份,不过MongoDB在设计之初就考虑到这个问题,将oplog的同一个操作执行多次,与执行一次的效果是一样的。
简单的说就是:
当Primary节点完成数据操作后,Secondary会做出一系列的动作保证数据的同步: 1:检查自己local库的oplog.rs集合找出最近的时间戳。 2:检查Primary节点local库oplog.rs集合,找出大于此时间戳的记录。 3:将找到的记录插入到自己的oplog.rs集合中,并执行这些操作。 local数据 库中的oplog.rs表,默认在64位机器上这个表是比较大的,占磁盘大小的5%,oplog.rs的大小可以在启动参数中设 定:--oplogSize 1000,单位是M。 注意:在副本集的环境中,要是所有的Secondary都宕机了,只剩下Primary。最后Primary会变成Secondary,不能提供服务。
以下情况需要考虑oplog 的大小:
1.同时对多个文档进行更新:这些操作会转换成幂等操作
2.以相同速度发生的涉及等数据量的删除和插入
3.大量的就地更新
各种情况下的同步状态:
1.初始化同步与复制
1.节点首次启动(新节点无数据)
2.节点变得过时(主节点已经重写了oplog,该节点并没有复制数据)这种情况下,从库数据将被移除
# 同步的具体步骤为:
1.所有的数据库会被克隆
2.使用源节点的oplog,变更会被应用到其数据集
3.最后在所有的集合上创建索引
2.正常操作--同步
正常情况下,辅助节点会选择一个成员来同步其数据,然后从其源的oplog中拉取操作
1.先将其操作应用到副本集
2.将op写入本地oplog中
3.一旦op写入到oplog中,继续请求下个oplog。
如果1 和 2 步骤之间失败了,那么就重头执行这些步骤。它会假设该操作还没执行过。
由于oplog是幂等的因此相同的操作可以被应用任意次数。
3.节点刚启动
当一个节点被启动时,会检查本地集合的lastOpTimeWritten。在该辅助节点上的最后一个op的时间
如果一个成员启动并找到ts条目,将会选择一个目标来从其进行同步并作为一个正常的同步过程。
如果没有找到ts条目,该节点会进行初始化同步过程。
副本集架构详解
1. Primary --- > 默认情况下,读写都是在Primary上操作的。
2. Secondary --> 通过oplog来重放Primary上的所有操作,拥有Primary节点数据的完整拷贝。默认情况下,不可写,也不可读。
根据不同的需求,Secondary又可配置为如下形式:
1> Priority 0 Replica Set Members
优先级为0的节点,优先级为0的成员永远不会被选举为primary。在mongoDB副本集中,允许给不同的节点设置不同的优先级。
优先级的取值范围为0-1000,可设置为浮点数,默认为1。拥有最高优先级的成员会优先选举为primary。 譬如,在副本集中添加了一个优先级为2的成员node3:27020,而其它成员的优先级为1, 只要node3:27020拥有最新的数据,那么当前的primary就会自动降级,node3:27020将会被选举为新的primary节点,
但如果node3:27020中的数据不够新,则当前primary节点保持不变,直到node3:27020的数据更新到最新。
2> Hidden Replica Set Members-隐藏节点
隐藏节点的优先级同样为0,同时对客户端不可见
使用rs.status()和rs.config()可以看到隐藏节点,但是对于db.isMaster()不可见。客户端连接到副本集时,会调用db.isMaster()命令来查看可用成员信息。
所以,隐藏节点不会受到客户端的读请求。
隐藏节点常用于执行特定的任务,譬如报表,备份,选举。
3> Delayed Replica Set Members-延迟节点
延迟节点会比primary节点延迟指定的时间(通过slaveDelay参数来指定)延迟节点必须是隐藏节点。
4> Arbiter
仲裁节点,只是用来投票,且投票的权重只能为1,不复制数据,也不能提升为primary。
仲裁节点常用于节点数量是偶数的副本集中。
建议:通常将Arbiter部署在业务服务器上,切忌将其部署在Primary节点或Secondary节点服务器上。
注:一个副本集最多有50个成员节点,7个投票节点。
mongodb 副本集能解决的问题:
- 主节点挂了能否自动切换连接?目前需要手工切换。
- 主节点的读写压力过大如何解决?
- 从节点每个上面的数据都是对数据库全量拷贝,从节点压力会不会过大?
- 数据压力大到机器支撑不了的时候能否做到自动扩展?
设置一个成员的选票为0 来禁用该成员的投票功能。可以担当候选人,但是不能进行投票。
cfg_1 = rs.conf()
cfg_1.members[3].votes=0
副本集搭建步骤
1.创建各种目录
sudo mkdir -p data/mongodb2.4/repl/{data,log}
2.配置文件:mongod.conf
dbpath=/data/mongodb2.4/repl/data logpath=/data/mongodb2.4/repl/log/mongod.log port=27091 logappend=true fork=true replSet=repset maxConns=20000
3.启动mongo
sudo /usr/local/mongodb2.4/bin/mongod -f /data/mongodb2.4/repl/mongod.conf
4.、初始化副本集
在任意一台机器上登陆mongo
#定义副本集配置变量,这里的 _id:”repset” 和配置文件中replSet=repset” 要保持一样
use admin > config={_id:'repset',members:[ ... {_id:0,host:'10.1.3.67:27091'}, ... {_id:1,host:'10.1.3.68:27091'}, ... {_id:2,host:'10.1.3.69:27091'}] ... } ##输出内容 {"_id" : "repset",
"members" : [ {"_id" : 0,"host" : "10.1.3.67:27091"}, {"_id" : 1,"host" : "10.1.3.68:27091"}, {"_id" : 2,"host" : "10.1.3.69:27091"} ]} ##初始化副本集配置 rs.initiate(config) > rs.initiate(config) { "info" : "Config now saved locally. Should come online in about a minute.", "ok" : 1 } #查看日志,确定没有问题 $ sudo tail -100 mongod.log
#查看各个节点状态:
rs.status()
#查看复制的情况
mongotag:SECONDARY> db.printReplicationInfo() configured oplog size: 10000MB log length start to end: 11216395secs (3115.67hrs) oplog first event time: Sun Dec 03 2017 15:54:02 GMT+0800 (CST) oplog last event time: Thu Apr 12 2018 11:33:57 GMT+0800 (CST) now: Thu Apr 12 2018 11:33:57 GMT+0800 (CST)
db.printSlaveReplicationInfo()
mongotag:SECONDARY> db.printSlaveReplicationInfo() source: 10.1.5.112:27017 syncedTo: Thu Apr 12 2018 11:34:12 GMT+0800 (CST) = 1 secs ago (0hrs) source: 10.1.5.112:27018 no replication info, yet. State: ARBITER
source:从库的ip和端口。
syncedTo:目前的同步情况,以及最后一次同步的时间。
#查看副本集的配置
rs.conf()/rs.config()
mongotag:PRIMARY> rs.config()
{
"_id" : "mongotag",
"version" : 163950,
"members" : [
{
"_id" : 2,
"host" : "10.1.5.112:27017",
"priority" : 6
},
{
"_id" : 3,
"host" : "10.1.5.111:27017",
"priority" : 10
},
{
"_id" : 4,
"host" : "10.1.5.112:27018",
"arbiterOnly" : true
}]
}
#增加/删除节点
repset:PRIMARY> rs.add('10.1.3.68:27091') repset:PRIMARY> rs.remove('10.1.3.68:27091')
#mongodb默认是从主节点读写数据的,副本节点上不允许读,需要设置副本节点可以读。
repset:SECONDARY> db.getMongo().setSlaveOk() #此操作只对当前连接有效 repset:SECONDARY> show tables col system.indexes repset:SECONDARY> db.col.find() { "_id" : ObjectId("5a0b9f9646d897f6484a6719"), "name" : "repset" }
副本集的实际应用场景
(1).手动切换Primary节点到自己给定的节点
优先级priority,因为默认的都是1,所以只需要把给定的服务器的priority加到最大即可
#修改新master的优先级 cfg=rs.conf() repset:PRIMARY> cfg.members[0].priority=2 2 #重载配置,强制了副本集进行一次选举,优先级高的成为Primary repset:PRIMARY> re.reconfig(cfg)
(2) 添加仲裁节点
#删除一个节点并重启 repset:PRIMARY> rs.remove('10.1.3.69:27091') #添加删除的节点使其成为arbiter repset:PRIMARY> rs.addArb('10.1.3.69:27091')此操作会导致关机。。。。。 #查看副本集的状态 rs.status() / rs.conf()
当所有的Secondary都宕机、或则副本集中只剩下一个节点,则该节点只能为Secondary节点,也就意味着整个集群智能进行读操作而不能进行写操作,当其他的恢复时,
之前的primary节点仍然是primary节点。
当某个节点宕机后重新启动该节点会有一段的时间(时间长短视集群的数据量和宕机时间而定)导致整个集群中所有节点都成为secondary而无法进行写操作(如果应用程序没有设置相应的ReadReference也可能不能进行读取操作)。
副本集要求参与选举投票(vote)的节点数为奇数,当我们实际环境中因为机器等原因限制只有两个(或偶数)的节点,这时为了实现 Automatic Failover引入另一类节点:仲裁者(arbiter),仲裁者只参与投票不拥有实际的数据,并且不提供任何服务,因此它对物理资源要求不严格。
通过实际测试发现,当整个副本集集群中达到50%的节点(包括仲裁节点)不可用的时候,剩下的节点只能成为secondary节点,整个集群只能读不能 写。
比如集群中有1个primary节点,2个secondary节点,加1个arbit节点时:当两个secondary节点挂掉了,那么剩下的原来的 primary节点也只能降级为secondary节点;
当集群中有1个primary节点,1个secondary节点和1个arbit节点,这时即使 primary节点挂了,剩下的secondary节点也会自动成为primary节点。因为仲裁节点不复制数据,因此利用仲裁节点可以实现最少的机器开 销达到两个节点热备的效果。
(3) 添加隐藏节点
hidden(成员用于支持专用功能):这样设置后此机器在读写中都不可见,并且不会被选举为Primary,但是可以投票,一般用于备份数据。
本实验将hidden节点和arbiter放在一个机器上
#添加节点 repset:PRIMARY> rs.add({_id:1,host:'10.1.3.69:27092',priority:0,hidden:true}) #查看 repset:PRIMARY> rs.conf() { "_id" : "repset", "version" : 7, "members" : [ { "_id" : 0, "host" : "10.1.3.67:27091", "priority" : 2 }, { "_id" : 3, "host" : "10.1.3.68:27091" }, { "_id" : 4, "host" : "10.1.3.69:27091", "arbiterOnly" : true }, { "_id" : 1, "host" : "10.1.3.69:27092", "priority" : 0, "hidden" : true }]}
(4)添加延迟节点
Delayed(成员用于支持专用功能):可以指定一个时间延迟从primary节点同步数据。主要用于处理误删除数据马上同步到从节点导致的不一致问题。
rs.add({"_id":3,"host":"192.168.200.25:27017","priority":0,"hidden":true,"slaveDelay":60})
Secondary-Only:不能成为primary节点,只能作为secondary副本节点,防止一些性能不高的节点成为主节点。
Non-Voting:没有选举权的secondary节点,纯粹的备份数据节点。
浙公网安备 33010602011771号