Mongodb副本集

Mongodb副本集

一、简介:

简单来说,副本集(Replica Set)就是有自动故障恢复功能的主从集群。主从集群和副本集最为明显的区别是副本集没有固定的“主节点”:整个集群会选举出一个“主节点”,当其不能工作时则变更到其他节点。然而,二者看上去非常相似:副本集总会有一个活跃节点(primary)和一个或多个备份节点(secondary)。

副本集最美妙的地方就是所有东西都是自动化的。首先他为你做了很多管理工作,自动提升备份节点为活跃节点,其次,对开发者而言也非常易用:仅需要为副本集指定一下服务器,驱动程序就会自动找到服务器,在当前活跃节点死机时自动处理故障恢复这类事情。

当活跃节点挂了,备份节点自动成为活跃节点。

当活跃节点又恢复了,由于已经有活跃节点了,自动变为备份节点。

二、副本集中的节点

1. Standard: 常规节点,存储了完整数据副本,参与投票,可能成为活跃节点,优先权非0.

2. Passive: 存储了完整数据副本,参与投票,不能成为活跃节点。优先权为0.

3. Arbiter:仲裁者,只参与投票,不接受复制的数据,也不能成为活跃节点。

如果活跃节点坏了,其他节点会选出一个新的活跃节点来。选举过程可以由任何非活跃节点发起。新的活跃节点由副本集中的大多数选举产生。仲裁节点也会参与投票,避免出现僵局。新的活跃节点将是优先级最高的节点,优先级相同则数据较新的获胜。

活跃节点使用心跳来跟踪集群中有多少节点对其可见。如果不够半数,活跃节点会自动降级为备份节点。这样就能防止活跃节点一直不放权。

不论活跃节点何时变化,新活跃节点的数据就被假定为系统的最新数据。其他节点的操作会回滚,即便之前的活跃节点恢复了工作。

选举:

在以下几种情景发生的时候,副本集通过选举来决定副本集中的primary节点:

·        当第一次初始化一个副本集的时候;

·        primary几点steps down的时候,出现这种情况可能是因为执行了replSetStepDown命令,或者是集群中出现了更适合当primary的节点,比如当primary节点和集群中其他大部分节点无法通信的时候,当primarysteps down的时候,它会关闭所有客户端的连接。

·        当集群中一个secondary节点无法和primary节点建立连接的时候也会导致一次election发生。

·        一次failover

·        执行rs.conf()命令。

在一次选举中包括hidden节点、仲裁者甚至正处于recovering状态的节点都具有投票权。默认配置中所有参与选举的节点具有相等的权利,当然在一些特定情况下,应明确的指定某些secondary会优先成为primary,比如一个远在千里之外异地机房的节点就不应该成为primary节点,选举的权重通过设置priority来调节,默认该值都是1,在前面简单副本集的搭建中已经介绍过了如何修改该值。

集群中任何一个节点都可以否决选举,即使它是non-voting member

·        如果发起选举的节点不具有选举权(priority0的成员);

·        发起选举的节点数据落后太多;

·        发起选举的节点的priority值比集群中其他某一个节点的小;

·        如果当前的primary节点比发起选举的节点拥有更新或同等新的数据(也就optime值相等或更大)。

·        当前的primary节点会否决,如果它拥有比发起选举的节点更新或相同新的数据。

首先获取最多选票的成员(实际上要超过半数)才会成为primary节点,这也说明了为什么当有两个节点的集群中primary节点宕机后,剩下的只能成为secondary,当primary宕掉,此时副本集只剩下一个secondary,它只有1,不超过总节点数的半数,它不会选举自己为primary

读扩展:

 

 

ReadReferences:

应用程序驱动通过read reference来设定如何对副本集进行读取操作,默认的,客户端驱动所有的读操作都是直接访问primary节点的,从而保证了数据的严格一致性。

Mongodb副本集_第1张图片

但有时为了缓解主节点的压力,我们可能需要直接从secondary节点读取,只需要保证最终一致性就可以了。

Mongodb副本集_第2张图片

MongoDB 2.0之后支持五种的readpreference模式:

 

primary:默认,只从主节点上进行读取操作;

primaryPreferred:在绝大部分的情形都是从主节点上读取数据的,只有当主节点不可用的时候,比如在进行failover10秒或更长的时间内会从secondary节点读取数据。

警告2.2版本之前的MongoDBReadPreference支持的还不完全,如果客户端驱动采用primaryPreferred实际上读取操作都会被路由到secondary节点。

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

secondaryPreferred:优先从secondary节点进行读取操作;

nearest:既有可能从primary,也有可能从secondary节点读取,这个决策是通过一个叫memberselection过程处理的。

 

MongoDB允许在不同的粒度上指定这些模式:连接、数据库、集合甚至单次的操作。不同语言的驱动基本都支持这些粒度。

同步

从节点第一次启动时,会对主节点数据进行完整的同步.从节点复制主节点上的每个文档,很耗资源.同步完成后,

从节点开始查询主节点的oplog并执行这些操作,以保证数据是最新的.

如果从节点的操作和主节点的相差很远,从节点就跟不上同步了.跟不上同步的从节点无法一直追赶主节点.因为

主节点oplog的所有操作太新了.从节点发生了宕机或着疲于应付读取时会出现这个情况,也会在执行完完整同步以后

反生类似的事,因为只要同步的时间太长,同步完成时,oplog可能已经操作了很多.

从节点跟不上同步时,复制就会停下来,从节点需要重新做完整的同步.可以用{"resync":1}命令手动执行从新同步,

也可以在启动从节点时使用--autoresync选项让其自动重新同步,重新同步的代价很高,应尽量避免,方法是配置

足够大的oplog,配置足够大的oplog能存放相当长的时间操作记录.大的oplog会占用更多的磁盘空间,则需要权衡一下.

默认的oplog大小是剩余磁盘空间的5%.

 

三、实例

准备:

两台服务器:

192.168.229.80:80服务器作为节点1,目录如下

/export/servers/dbs/node1/

Mongodb副本集_第3张图片

192.168.192.75:75服务器作为节点2,目录如下

Mongodb副本集_第4张图片

启动node1节点:80:

-bash-3.2# ./bin/mongod --dbpath ./data/node1 --logpath ./data/node1/node1.log --port 10001 --replSet test/192.168.192.75:10002

启动node2节点:75:

[root@localhost mongodb-linux-x86_64-2.0.4]# ./bin/mongod --dbpath ./data/node2/ --port 10002 --replSet test/

 

通过192.168.192.68链接到一台服务器:

./bin/mongo 192.168.229.80:10001/admin                                                                                                                            

初始化副本集:

 db.runCommand({

 "replSetInitiate":{

  "_id":"test",

  "members":[

   {

     "_id":1,

     "host":"192.168.229.80:10001"                                                                                                                                            ,

      "priority":3

   },

   {

     "_id":2,

     "host":"192.168.192.75:10002",

     "priority":2

   }

    ]

 }

});

 

结果如图:提示ok:1即成功,间有几次报错是磁盘满了,清除后ok

 Mongodb副本集_第5张图片

查看副本集状态:

Mongodb副本集_第6张图片

查看是否为主节点:看到ismaster:true

 Mongodb副本集_第7张图片

切换到75上查看:ismaster:false

 Mongodb副本集_第8张图片

往主库插入数据:

Mongodb副本集_第9张图片

去从库查看:

Mongodb副本集_第10张图片

发现查不到数据,这是正常的,因为SECONDARY是不允许读写的,在写多读少的应用中,使用Replica Sets来实现读写分离。通过在连接时指定或者在主库指定slaveOk,由Secondary来分担读的压力,Primary只承担写操作。

对于replica set 中的secondary 节点默认是不可读的,分别从从库和主库设置setSlaveOk即可。

参考:

http://www.cnblogs.com/refactor/archive/2012/08/13/2600140.html

你可能感兴趣的:(数据库)