前言
在技术社区混了这么长时间,因为一些常见的技术问题反复被问到,总是想写写文章把它们讲清楚。无奈很多时候看似基础的技术问题背后都隐藏着很深的原因,想要一次性说清楚太花时间,而平时又没有很多时间能花在上面(主要是懒),所以产生了写一系列文章的想法,讲讲我或我的客户使用MongoDB过程中经常遇到的各种“坑”。话虽如此,难者不会会者不难,希望看了这些讲解你就不再认为这些是“坑”了。
在讲解这些问题前,我会假设读者已经对MongoDB有了最基础的了解,因此一些基本名词和概念就不做过多的解释,请自己查阅相关资料。
PSS vs PSA
什么是PSS/PSA?
在MongoDB复制集中,存在三种类型的角色:
- PRIMARY: 主节点(P)
- SECONDARY: 从节点(S)
- ARBITER: 仲裁节点(A)
构建一个复制集至少需要3个节点,所以用户就有了两种选择,即PSS和PSA。
注意:记住A的作用始终是把集群中具有投票权的节点总数凑成奇数用,防止“脑裂”。因此诸如PAA,PSSAA之类的配置是没有存在的意义的,极端情况下还会扰乱集群的正常工作。
PSA有什么好处?
最直接的好处:省钱啊!随便找台机器,不消耗什么资源就可以运行一个A,比一个S的成本小多了。
PSA有什么问题?
读写失效
最直接的问题来自于MongoDB中的一个配置选项{w: "majority"}
,这个配置决定了一次成功的写入操作需要到达多少个节点才算真正的成功,w
可以定义为1,2,...n(n<=集群节点总数)或majority
。而majority
是保证在集群故障时不丢失数据的必要配置(关于majority
和w
以后再专门写文章讨论)。其代表的意义是:集群中必须有大多数节点收到并确认了一个写操作,这个写操作才算成功。
在三个节点的集群中,{w: "majority"} == {w: 2}
。因此如果集群配置是PSA,由于A是不存数据的,所以集群中能够确认写操作的节点只有P和S,刚好是2。到这里可能有人已经看出问题了:在PSA中如果有一个数据节点宕机,则再也不能满足{w: "majority"}
,所有使用这种配置的写操作都会失败。因此可以说,PSA在一定程度上丢失了高可用性,因为任何一个数据节点的失效都会导致{w: "majority"}
类型写入的失败。
引申一下,ReadConcern
同样有可选值majority
,因此同样可能因为一个数据节点的失效而失效。
集群部分功能失效
可能你会觉得:什么{w: "majority"}
没听说过啊,我也不在乎丢失数据,那用PSA是不是就没有问题了?当然不是!在很多你没注意到的场景都存在着{w: "majority"}
。比如:
- 分片集群数据迁移。无论源或者目标片中不能够满足大多数时,迁移都会失败。
-
分片集群管理。包括但不限于以下这些操作实际上都隐含着
{w: "majority"}
。一旦不能满足,这些操作都会失败:db.dropDatabase()
db.collection.drop()
db.collection.dropIndex({...})
sh.shardCollection(...)
db.createUser(...)
结论
majority
比你想象的更重要,PSA不能够提供足够的可用数据节点来保证majority
,因此在很多场景下会引发隐藏的错误。在有可能的情况下,应尽量使用PSS代替PSA。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。