MongoDB——副本集成员配置

选举仲裁者

仲裁者的唯一作用就是参与选举。仲裁者并不保存数据,也不会为客户端提供服务:它只是为了帮助具有两个成员的副本集能够满足“大多数”这个条件。

由于仲裁者并不需要履行传统mongod服务器的责任,所以可以将仲裁者作为轻量级进程,运行在配置比较差的服务器上。如果可能,应该将仲裁者放在单独的故障域(failure domain)中,与其他成员分开。这样它就可以以“外部视角”来看待副本集中的成员了。
启动仲裁者与启动普通mongod的方式相同,使用"--replSet 副本集名称"和空的数据目录。可以使用rs.addArb()辅助函数将仲裁者添加到副本集中:

rs.addArb("server-5:27017")

也可以在成员配置中指定arbiterOnly选项,这与上面的效果是一样的:

rs.add({"_id":4, "host":"server-5:27017", "arbiterOnly":true})

成员一旦以仲裁者的身份添加到副本集中,它就永远只能是仲裁者:无法将仲裁者重新配置为非仲裁者,反之亦然。
使用仲裁者的另一个好处是:如果你拥有的节点数是偶数,那么可能会出现一半节点投票给A,但是另一半成员投票给B的情况。仲裁者这时就可以投出决定胜负的关键一票。

  1. 最多只能使用一个仲裁者
    注意,在上面的例子中,最多只需要一个仲裁者。如果节点数量是奇数,那就不需要仲裁者。一种错误的理解是:为了“以防万一”,总是应该添加额外的仲裁者。但是,添加额外的仲裁者,并不能加快选举速度,也不能提供更好的数据安全性。
    假设有一个3成员的副本集。需要两个成员才能组成“大多数”,才能选举主节点。如果这时添加了一个仲裁者,副本集中总共就有4个成员了,要有3个成员才能组成“大多数”。因此,副本集的稳定性其实是降低了:原本只需要67%的成员可用,副本集就可用;现在必须要有75%的成员可用,副本集才可用。
    添加额外成员也会导致选举耗时变长。由于添加了仲裁者,现在副本集一共拥有偶数个成员,这样就可能出现两个成员票数相同的情况。仲裁者的目的应该是避免出
    现平票,而不是导致出现平票。

  2. 仲裁者的缺点
    不知道应该将一个成员作为数据节点还是作为仲裁者时,应该将其作为数据节点。在小副本集中使用仲裁者而不是数据节点会导致一些操作性的任务变困难。假设有一个副本集,它有两个“普通”成员,还有一个仲裁者成员,其中一个数据成员挂了。如果这个数据成员真的挂了(数据无法恢复),另一个数据成员成为主节点。这时整个副本集中只有一个数据成员和一个仲裁者成员。为了保证数据安全,就需要一个新的备份节点,并且将主节点的数据副本复制到备份节点。复制数据会对服务器造成很大的压力,会拖慢应用程序。通常,将几GB的数据复制到新服务器可以很快完成,不会对服务器和应用程序造成显著影响,但是如果要复制100GB以上的数据,问题就会很严重了。
    相反,如果拥有三个数据成员,一个服务器挂掉时,副本集中仍然有一个主节点和一个备份节点,不会影响正常运作。这时,可以用剩余的那个备份节点来初始化一个新的备份节点服务器,而不必依赖于主节点。
    在上面两个数据成员+一个仲裁者成员的情景中,主节点是仅剩的一份完好的数据,它不仅要处理应用程序请求,还要将数据复制到另一个新的服务器上。如果可能,尽可能在副本集中使用奇数个数据成员,而不要使用仲裁者。

优先级

优先级用于表示一个成员渴望称为主节点的程度。优先级的取值范围可以是0~100,默认是1。将优先级设为0有特殊含义:优先级为0的成员永远不能够成为主节点。
这样的成员称为被动成员(passive member)。拥有最高优先级的成员会优先选举为主节点(只要它能够得到集合中“大多数”的赞成票,并且数据是最新的)。假如在副本集中添加了一个优先级为1.5的成员:

rs.add ({"_id":4,"host""server4:27017","priority":1.5})

假设其他成员的优先级都是1,只要server4拥有最新的数据,那么当前的主节点就会自动退位,server4会被选举为新的主节点。如果server4的数据不够新,那么当前主节点就会保持不变。设置优先级并不会导致副本集中选不出主节点,也不会使数据不够新的成员成为主节点(一直到它的数据更新到最新)。

使用优先级时有一点需要注意:修改副本集配置时,新的配置必须要发送给在新配置下可能成为主节点的成员。因此,无法在一次reconfig操作中将当前主节点的优先级设置为0,也不能对所有成员优先级都为0的副本集执行reconfig。

优先值的值只会影响副本集成员间相对优先级大小关系。如果某个副本集3个成员的优先级是500、1、1,另一个副本集3个成员的优先级是2、1、1,那么它们的行为是一样的。

隐藏成员

客户端不会向隐藏成员发送请求,隐藏成员也不会作为复制源(尽管当其他复制源不可用时隐藏成员也会被使用)。因此,很多人会将不够强大的服务器或者备份服务器隐藏起来。
假设有一副本集如下所示:

rs.isMater() {
	...
	"hosts" : [
		"server1:27017",
		"server2:27017",
		"server3:27017"
	],
	...
}

为了隐藏server3,可以在它的配置中指定hidden:true。只有优先级为0的成员才能被隐藏(不能将主节点隐藏):

var config = rs.config()
config.members[2].hidden = 0
config.members[2].priority = 0
rs.reconfig(config)

现在,执行isMaster()可以看到:

rs.isMaster() 
{
	...
	"hosts": [
		"server1:27017",
		"server2:27017"
	],
	...
}

使用rs.status()和rs.config()能够看到隐藏成员,隐藏成员只对isMaster()不可见。客户端连接到副本集时,会调用isMaster()来查看可用成员。因此,隐藏成员不会收到客户端的读请求。要将隐藏成员设为非隐藏,只需将配置中的hidden设为false就可以了,或者删除hidden选项。

延迟备份节点

数据可能会因为人为错误而遭受毁灭性的破坏:可能有人不小心删除了主数据库,或者刚上线的新版应用程序有一个严重bug,把所有数据都变成了垃圾。

为了防止这类问题,可以使用slaveDelay设置一个延迟的备份节点。延迟备份节点的数据会比主节点延迟指定的时间(单位是秒),这是有意为之。这样,如果有人不小心摧毁了你的主集合,还可以将数据从先前的备份中恢复过来。
slaveDelay要求成员的优先级是0。如果你的应用会将读请求路由到备份节点,应该将延迟备份节点隐藏掉,以免读请求被路由到延迟备份节点。

创建索引

有时,备份节点并不需要与主节点拥有相同的索引,甚至可以没有索引。如果某个备份节点的用途仅仅是处理数据备份或者是离线的批量任务,那么你可能希望在它的成员配置中指定"buildIndexs":false。这个选项可以阻止备份节点创建索引。

这是一个永久选项,指定了"buildIndexes"::false的成员永远无法恢复为可以创建索引的“正常”成员。如果确实需要将不创建索引的成员修改为可以创建索引的成员,那么必须将这个成员从副本集中移除,再删除它的所有数据,最后再将它重新添加到副本集中,并且允许它重新进行数据同步。另外,这个选项也要求成员的优先级为0。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值