Primary节点接收客户端所有的写操作,整个副本集只会有一个primary节点。MongoDB副本集提供严格的一致性。主节点将所有的操作写入一个叫oplog的capped collection(这个collection的大小一般为磁盘剩余空间的5%,不同的系统可能不一样,详见http://docs.mongodb.org/manual/core/replica-set-oplog/)中,secondary节点通过复制oplog并执行oplog中的所有操作,因为对oplog的执行是幂等的,所以secondary节点上的数据可以保持和primary节点一样,当然这有一个“追赶”(catch up)的过程,会存在一定的落后(Lag)有时候因为网络延迟或宕机导致从节点永远赶不上主节点,这时候需要采取人为的干预了(后面会说到Resyncing Member of Replica Set)。
默认所有的读操作也是走的primary节点,当然客户端可以选择从secondary节点进行读取操作以减小主节点的压力(后面会对读写分离有详细说明)。
各个节点之间是通过心跳机制来维持联系的,当主节点无法和集群中其他节点通信超过10秒,集群会从剩下的节点中选择一个secondary作为primary,这个过程叫做选举(election),每个secondary节点都有一个优先级priority来参与投票(也可以有没有投票权的secondary节点),priority值越大就越优先成为主节点(所有的节点可以有相同的优先级,默认值都是1)。election的策略不仅仅就是根据priority值来,会综合很多其他的因素。总之MongoDB通过heartbeat和election机制实现了自动的Failover:
副本集要求参与选举投票(vote)的节点数为奇数,这很容易理解。当我们实际环境中因为机器等原因限制只有两个(或偶数)的节点,这时为了实现Automatic Failover引入另一类节点:仲裁者(arbiter),仲裁者只参与投票不拥有实际的数据,因此它对物理资源要求不严格。
上面已经提到了primary,secondary和arbiter,整个MongoDB副本集群中除了这三种类型的节点还有其他几种:
- Secondary-Only:这种类型的节点和secondary节点一样拥有数据副本,但是它们在任何情形下都成为不了primary节点。
- Hidden:这种类型的节点对客户端程序来说是不可见的,同样也不能成为primary节点,但是Hidden成员能够参与选举投票。
- Delayed:这种类型的成员通过人为的设置,可以指定一个时间来延迟从primary节点同步数据。Delayed成员的作用在于帮助集群从一些误操作中恢复,比如管理员误删除了某个集合。不至于迅速扩散到整个集群中。因此Delayed节点必须不能成为primary节点(priority为0)并且是Hidden的。
- Non-Voting:这就是上面提到了没有选举权的secondary节点。这种类型的节点一般当集群节点数超过12才会需要。
环境:
192.168.1.1(primary)
192.168.1.2(secondary)
192.168.1.3(secondary)
开启防火
iptables -I INPUT -p tcp --dport 27018 -j ACCEPT
一、分别在三台服务器上 编辑配置文件
#配置文件mongodb.conf存放路径为 /opt/confg/mongo/mongodb.conf
dbpath=/opt/mongodb/data/
logpath=/var/log/mongodb/mongodb.log
pidfilepath=/opt/mongodb/data/mongodb.pid
logappend=true
fork=true
port=27017
quiet=true
directoryperdb=true
replSet=replSet01
oplogSize=10240 #(MB单位)
maxConns=20000
二、分别启动三台服务器上的mongod服务
mongod -f /opt/confg/mongo/mongodb.conf
或
runuser -c "/opt/mongodb/bin/mongod -f /opt/confg/mongo/mongodb.conf " mongod
三、初始化副本集配置
登录任意一台服务器的mongo服务: mongo --port 27017
use admin
mongo>conf={_id :"replSet01",
"members":[{_id:1,"host":"192.168.1.1:27017",priority:3}, {_id :2,"host":"192.168.1.2:27017",priority:2},{_id :3,"host":"192.168.1.3:27017",priority:1}]}
mongo>rs.initiate(conf);
或者
db.adminCommand({"replSetInitiate":{_id:"replSet01",members:[{_id:1,host:"192.168.1.1:27017"},{_id:2,host:"192.168.1.2:27017"},{_id:3,host:"192.168.1.3:27017"}]}})
///////////////////////cnf_rplset的语法(将3台服务器串起来的语法选项)/////////////////////////////
{
_id : <setname>,
members: [
{
_id : <ordinal>,
host : <hostname[:port]>
[, arbiterOnly : true]
[, buildIndexes : <bool>]
[, hidden : true]
[, priority: <priority>]
[, tags: {loc1 : desc1, loc2 : desc2, ..., locN : descN}]
[, slaveDelay : <n>]
[, votes : <n>]
}
, ...
],
[settings: {
[getLastErrorDefaults: <lasterrdefaults>]
[, getLastErrorModes : <modes>]
}]
}
详细说明:(默认值在括号中)
_id:副本集的名字,必须和命令行的名字匹配,也就是您刚才启动mongodb数据库命令行的那个名字,数字字母,不能包含"/";
members:一个数组用来表示副本集中的每个成员,这个数组必须包含_id和host这2个key。
members 数组:
_id:在副本集中的每一个成员都必须有一个_id表示,这个_id是通常是数字,从0开始增长。需要注意的是当其中一个成员退休了(指从副本集config中移除了),新加入的成员不能重新使用这个退休成员的_id;
host:ip地址和端口号;
arbiterOnly(false):如果是true,则表示这个成员为仲裁节点,不接收数据;
buildIndexes(true):如果设置为false,则会阻止在这个节点上创建第二索引,通常这个节点是作为纯粹的数据备份,从不用来被查询。不过也因为此节点没有第二索引,所以他写入的东西很少,也就需要很少的内存和磁盘。_id的索引还是会被创建的。只有当priority属性设置为0时,此项才能设置为false,一般不会用到这个选项;
hidden(false):如果此项为true,不要告诉客户端的此节点的存在,设置隐藏节点的原因是此节点的数据的使用模式和其他节点大为不同,比如:报表,统计,备份等。设置为ture时,允许你针对这个节点发送非主要查询。
priority(1.0):权重,更高的权重会被选举为主节点.取值范围0-100,数字越大优先级越高,0代表永不能成为主节点。只有优先级为0(即被动成员)才可以设置为隐藏成员(hidden=0)
tags({}):一个文档代表这台服务器的位置,有利于位置感知的读写。其实就是表示此节点位于哪个数据中心的,mongodb会根据tags找近的数据中心节点同步数据。
slaveDelay(0):同步数据的延迟,设置为0表示立即更新同步数据。
votes(1):此节点可以发出的投票数,一般不用修改他
settings 对象:settings对象可以在集群建立起来以后用再进行设置,通常使用默认值
设置成员优先级
var config=rs.config()
config.members[1].priority=0
rs.reconfig(config);
设置成员为隐藏节点
var config=rs.config()
config.members[1].priority=0
config.members[1].hidden=0
rs.reconfig(config)
隐藏成员在isMaster()是看不到的。但是在rs.status() 和rs.config()是可见的。因为客户端连接到副本集时,首先会调用 isMaster()来查看可用成员。隐藏成员是不会接受客户端的读请求的。
如果想让节点变为 延迟备份节点 (slaveDelay 属性)那么该节点的优先级也必须是 0 和隐藏成员,目的是避免路由服务奖客户的读请求路由到该备份节点。
//////////////////////////cnf_rplset的语法(将3台服务器串起来的语法选项)/////////////////////////////