一,设计复制集
选择主节点时需要大多数决定,主节点只有在得到大多数支持时才能继续作为主节点,写操作被复制到大多数成员时这个写操作就是安全的。这里的大多数被定义为“复制集”中一半以上的成员。
复制集中的成员数量 | 复制集中的大多数 |
1 | 1 |
2 | 2 |
3 | 2 |
4 | 3 |
5 | 3 |
6 | 4 |
7 | 4 |
假如有一个包含5个成员的复制集,其中3个成员不可用,仍然有2个可以正常工作,剩余的2个成员已经无法达到复制集“大多数”的要求(在这个例子中,至少要有3个成员才算“大多数”),所以它们无法选举主节点。如果这两个成员中有一个是主节点,当它注意到它无法得到“大多数”成员支持时,就会从主节点上退位。几秒钟后,这个复制集中会包含2个secondary节点和3个不可到达成员。
如果要求被选举为主节点的成员能够得到复制集中“大多数”成员的投票,它就会成为主节点、只要有一个成员投了否决票,选举就会取消。如果成员发现任何问题,表明当前希望成为主节点的成员不应该成为主节点,那么它就会否决此次选举。
关于仲裁者arbiter:
仲裁者的唯一作用就是参与选举。仲裁者并不保存数据,也不会为客户端提供服务,它只是为了帮助满足“大多数”这个条件。
关于优先级:
优先级用于表示一个成员渴望成为主节点的程度。优先级的取值范围可是0~100,默认是1,。将优先级设为0有特殊含义:优先级为0的成员永远不能够成为主节点。这样的成员成为被动成员(passive member)。
关于隐藏成员:
客户端不会向隐藏成员发送请求,隐藏成员也不会作为复制源(尽管当其他复制源不可用时隐藏成员也会被使用)。因此,很多人会将不够强大的服务器或者备份服务器隐藏起来。
关于延迟备份节点:
数据可能会因为人为错误而遭受毁灭性的破坏:可能有人不小心删除了主数据库,或者刚上线的新版应用程序有一个严重bug,把所有数据都变成了垃圾。为了防止这类问题,可以使用slaveDelay设置一个延迟的备份节点。
延迟备份节点的数据比主节点延迟指定的时间(单位是秒),这是有意为之。这样,如果有人不小心摧毁了你的集合,还可以将数据从先前的备份中恢复过来。
slaveDelay要求成员的优先级是0。如果你的应用会将读请求路由到备份节点,应该讲延迟备份节点隐藏掉,以免读请求被路由到延迟备份节点。
关于投票:
一个复制集最多可以有50个成员,但是最多只有7个成员(包括primary节点)有投票权。
二,写关注
对于某些应用程序来说,写关注是重要的。它能判断哪些写操作成功写入了,哪些失败了。对于失败的操作,驱动程序能返回错误,由应用程序决定怎么处理。如果没有写关注,应用程序发送一个写操作到socket后,就不会管后面发生了什么情况,不知道是否成功写入数据库,这种情形对于日志类型的应用程序还是可以接受的,因为偶尔的写失败不会影响整个日志的监控情况。带有写关注的操作会等到数据库确认成功写入后才能返回,因此写关注会带来一点性能的损失。
默认情况下复制集的写关注只针对primary节点,当应用程序发送一个写操作请求时,驱动程序只会调用getLastError命令返回写操作的执行情况(这一动作对驱动程序来说是透明的),getLastError命令会根据我们配置的写关注选项执行。写关注选项的配置是针对当前客户端与数据库的socket连接来说的,因此配置项需要通过应用程序传递给驱动程序。当然如果我们没有传递任何选项参数给驱动程序,getLastError命令会根据配置在复制集中的默认配置local.system.replset.settings.getLastErrorDefaults来执行。
getLastError命令的常用选项如下。
1,选项w
当取值为-1时,驱动程序不会使用写关注,忽略掉所有的网络或socket错误。
当取值为0时,驱动程序不会使用写关注,只返回网络和socket的错误。
当取值为1时,驱动程序使用写关注,但是只针对primary节点,这个配置项是对于复制集或单mongod实例默认写关注配置。
当取值为整数且大于1时,写关注将针对复制集中的n个节点,当客户端收到这些节点的反馈信息后,命令才返回给客户端继续执行。
如图所示就是一个w值等于2的写关注执行流程图,其中w的值为2,表示一个primary节点和一个secondary节点。
2,选项wtimeout
指定写关注应在多长时间内返归,如果你没有指定这个值,复制集可能因为不确定因素导致应用程序的写操作一直阻塞。
三,读参考
读参考是指MongoDB将客户端的读请求路由到复制集中指定的成员上,默认情况下读操作的请求被路由到复制集的primary节点上。从primary节点上进行读取能够保证读到的数据是最新的,但是将读操作路由到其他secondary节点上去后,由于从primary节点同步数据到secondary节点会产生时间差,可能导致从secondary节点上读到的数据不是最新的。当然这对于实时性要求不是很高的绝大部分应用程序来说,并不是大问题。
因为每一个secondary节点都会从primary节点同步数据,所有secondary节点一般有相同的写操作流量,同时primary节点上的读操作量也并没有减少,所以读参考并不能提高系统读写的容量。它最大的好处是能够使客户端的读请求路由到最佳的secondary节点上(如最近的节点),提高客户端的读效率,MongoDB驱动支持的读参考模式如下。
1,primary模式
这是默认的读操作模式,所有的读请求都路由到复制集中的primary节点上。如果primary节点故障了,读操作将会产生一个错误或者抛出一个异常。
2,primarypreferred模式
在大多数模式下,读操作从primary节点上进行,如果primary节点故障无法读取,读操作将被路由到secondary节点上。
3,secondary模式
读操作只能从secondary节点上进行,如果没有可用的secondary节点,读操作将产生错误或抛出异常。
4,secondaryPreferred模式
在大多数情况下,读操作在secondary节点上进行,但当复制集中只有一个primary节点时,读操作将用这个复制集的primary节点。
5,nearest模式
读操作从最近的节点上进行,有可能是primary节点,也有可能是secondary节点,并不会考虑节点的类型。
四,标签
如果正在使用写关注或者读参考,你可能会想要更细粒度地进行控制,控制哪个节点接受写或读请求。例如,假设部署了一个五节点复制集,跨两个数据中心:NY和FR。主数据中心NY 包含三个节点,从数据中心FR包含剩下的两个节点。假设希望通过写关注阻塞请求,直到写操作被复制到数据中心FR的至少一个节点上。
复制集标签可以实现这个需求,它允许针对带有特定标签的复制集成员定义特殊的写关注模式。
五,日志
当MongoDB向复制集中的primary节点写数据时,也会将写操作日志oplog写到primary节点所在的local数据库中,因此对复制集的写操作会产生两个锁,一个是集合数据所在的数据库上的写锁,还有一个是local数据库上的写锁。