文章目录
-
- 一、引入复制集的原因
- 二、复制集成员
- 三、复制集常见部署架构
- 四、复制集保证数据高可用的机制
- 五、复制集中的OptLog
- 六、复制集中的数据同步
- 七、注意事项
- 八、复制集读写关注 (concern)
-
- (一)读的优先级 (Read Preference)
- [(二)Write Concern](#(二)Write Concern)
- 九、复制集性能优化
- 十、安全相关考虑
- 十一、复制集的监控与管理
一、引入复制集的原因
- 数据冗余与可靠性:保证数据在生产部署时的冗余和可靠性,通过在不同机器保存副本,防止单点损坏导致数据丢失,应对数据丢失、机器损坏风险。
- 提高读取能力:用户的读取服务器和写入服务器分离,不同服务器为不同用户服务,提高系统负载。
二、复制集成员
(一)基本成员
- 主节点(Primary):包含所有写操作日志,副本服务器集群有其所有数据,主服务器挂掉时,副本服务器中会重新选取一个成为主服务器。
- 从节点(Secondary):正常情况下参与Primary选举(自身也可能被选为Primary),从Primary同步最新写入的数据以保证数据相同,可提供读服务,增加Secondary节点可提升读服务能力和复制集可用性。Mongodb支持对Secondary节点灵活配置以适应多种场景。
- 仲裁节点(Arbiter):只参与投票,不能被选为Primary,不从Primary同步数据。当部署偶数个节点的复制集(如2个节点,1个Primary,1个Secondary),任意节点宕机复制集不能提供服务时,添加一个Arbiter节点,即使有节点宕机仍能选出Primary。Arbiter不存储数据,是轻量级服务。
(二)主节点(Primary)细化成员
-
Priority0 :可作为备用,选举优先级为0,不会被选举为Primary。例如跨机房部署复制集,可指定某个机房的成员为Priority0,确保Primary在指定机房(注意:这种情况下多数节点最好部署在指定机房,否则网络分区时可能无法选出Primary)。
-
Hidden :客户端不会把读请求分发到隐藏节点,隐藏节点不会收到应用程序请求,可专用于报表节点或备份节点,延时节点也应为隐藏节点,不能被选为主(Priority为0),对Driver不可见,可用于数据备份、离线计算等不影响复制集服务的任务。
-
Delayed:数据集是延时的,可在人为误操作或其他意外情况(如应用升级失败、误删表或数据库)下恢复数据。Delayed节点必须是Hidden节点,数据落后Primary一段时间(可配置),当错误或无效数据写入Primary时,可通过Delayed节点数据恢复到之前时间点。
三、复制集常见部署架构
(一)基础三节点
-
一主两从方式 :一个主节点和两个从节点组成。主节点宕机时,两个从节点可竞选主节点,原主节点恢复后作为从节点加入复制集群。
-
一主一从一仲裁方式 :一个主节点、一个可竞选主节点的从节点和一个只参与投票的仲裁节点。主节点宕机时,从节点成为主节点,主节点修复后加入现有复制集群。
(二)跨数据中心
-
单个数据中心的复制集易受故障影响,多个数据中心可保护数据:在备用数据中心至少保留一个成员,尽量使用奇数个数据中心,合理分布成员,使在丢失数据中心时其余成员能构成多数或提供足够副本。
-
三个节点的分布情况
- 两个数据中心:两个成员在数据中心1,一个成员在数据中心2。若成员之一是仲裁者,将仲裁者与一个承载数据的成员放于数据中心1。数据中心1故障时复制集变为只读,数据中心2故障时复制集保持可写。
- 三个数据中心:每个数据中心各一个成员,任何数据中心故障时复制集保持可写。在两个数据中心分布成员有优势,若一个数据中心故障,数据仍可读取,少数成员数据中心故障时复制集仍可读写,多数成员数据中心故障时复制集变为只读,尽量在至少三个数据中心分配成员,配置服务器复制集(CSRS)最佳做法是在三个(或更多)中心之间分布,若第三个数据中心成本高,可在两个数据中心平均分配数据承载成员,其余成员存于云中。
-
五个节点的分布情况(相关注意事项和三个节点一致)
- 两个数据中心:数据中心1三个成员,数据中心2两个成员。数据中心1故障时复制集变为只读,数据中心2故障时复制集保持可写。
- 三个数据中心 :数据中心1、2各两个成员,数据中心3一个成员,任何数据中心故障时复制集保持可写。
-
数据转移的优先级 :将不应成为主要成员的成员配置为priority0,可修改priority成员使一个数据中心中成员优先级高于其他数据中心成员。
四、复制集保证数据高可用的机制
(一)选举机制
- 如何选出Primary主节点:假设复制集内能够投票的成员数量为N,则大多数为N/2 + 1,当存活成员数量不足大多数时,复制集无法选举出Primary,无法提供写服务,处于只读状态(如3投票节点需2个赞成票,容忍选举失败次数为1;5投票节点需3个赞成票,容忍选举失败次数为2,通常投票节点为奇数以减少选举失败概率)。
- 触发选举机制的情况:新加入节点、初始化复制集、对复制集进行维护(如rs.stepDown () 或者rs.reconfig () 操作)、从节点失联(如超时,默认10秒)。
- 具备选举权的成员状态:同时可投票的节点必须属于PRIMARY、SECONDARY、STARTUP2、RECOVERING、ARBITER、ROLLBACK状态之一,一个复制集最高可有50个节点,但只有7个投票节点,非投票节点votes是0(vote0)且priority是0(priority0)。
- 影响选举的因素 :选举协议(v4之前是pv0,v4开始为pv1)、心跳、成员权重、数据中心失联、网络分区、镜像读取(MongoDB v4.4开始提供的功能)。
(二)故障转移期间的回滚
当成员在故障转移后重新加入复制集时,回滚会还原以前主节点在数据库上的写操作,保证数据一致性。仅当主服务器接受了在其降级之前辅助服务器未成功复制的写操作时才需要回滚,主数据库作为辅助数据库重新加入集合时会还原或 "回滚" 其写入操作。
五、复制集中的OptLog
(一)什么是OptLog
MongoDB在主节点应用数据库操作后将其记录到optlog中,从节点通过异步进程复制和应用(数据同步)这些操作。所有复制集成员都在local.oplog.rs集合中有op log的副本以维护数据库当前状态。MongoDB 4.4支持以小时为单位指定最小操作日志保留期,仅在oplog达到最大大小或oplog条目早于配置小时数时删除操作日志条目。
(二)设计OptLog需考虑的因素
包括查看操作日志状态、设置操作日志大小(默认大小)、保存时长、哪些情况需设置更大以及对操作慢的管理和设置等,可参考官方文档 - Replica Set Oplog。
六、复制集中的数据同步
(一)初始同步 (Initial Sync)
- 需要全量同步的情况:从节点出现oplog为空、local.replset.minvalid集合里 _initialSyncFlag字段设置为true、内存标记initialSyncRequested设置为true这三种情况时需全量同步,分别对应新节点加入无oplog、initial sync开始和用户发送resync命令。
- initial sync流程:全量同步开始,设置minvalid集合的 _initialSyncFlag,获取同步源上最新oplog时间戳为t1,全量同步集合数据,获取同步源上最新oplog时间戳为t2,重放 [t1, t2] 范围 内的所有oplog,获取同步源上最新oplog时间戳为t3,重放 [t2, t3] 范围内所有的oplog,建立集合所有索引,获取同步源上最新oplog时间戳为t3,重放 [t3, t4] 范围内所有的oplog,全量同步结束,清除minvalid集合的 _initialSyncFlag。
(二)复制 (Replication)
initial sync结束后,Secondary会不断拉取主节点上新产生的optlog并重放。这个过程涉及producer thread(从同步源拉取oplog并放入BlockQueue队列)、replBatcher thread(从producer thread的队列取出oplog并放入自己维护的队列)、sync线程(将replBatcher thread的队列分发给16个replWriter线程重放oplog)。这样设计是出于性能考虑(拉取oplog单线程进行,重放若在拉取线程会使同步很慢)以及保证oplog重放顺序性(遇到DDL命令不能与其他增删改查命令并行执行,由replBatcher控制)。
七、注意事项
- initial sync单线程复制数据效率低,生产环境应尽量避免,合理配置oplog,默认按 "5%的可用磁盘空间" 配置oplog在大部分场景能满足需求,特殊情况可按需设置更大。
- 新加入节点可通过物理复制方式(将Primary上的dbpath拷贝到新节点并启动)避免initial sync,提高效率。
- 当Secondary需要的oplog在同步源上已滚掉时,Secondary同步会进入RECOVERING状态,需向Secondary主动发送resyc命令重新同步。
- 生产环境最好通过db.printSlaveReplicationInfo () 监控主备同步滞后情况,当Secondary落后太多要及时调查原因,若因主上并发写入太高导致Secondary同步滞后(db.serverStatus ().metrics.repl.buffer.sizeBytes持续接近db.serverStatus ().metrics.repl.buffer.maxSizeBytes),可通过调整Secondary上replWriter并发线程数提升。
八、复制集读写关注 (concern)
(一)读的优先级 (Read Preference)
- primary:默认规则,所有读请求发到Primary。
- primaryPreferred:Primary优先,如果Primary不可达,请求Secondary。
- secondary:所有读请求发到secondary。
- secondaryPreferred:Secondary优先,当所有Secondary不可达时,请求Primary。
- nearest:读请求发送到最近的可达节点(通过ping探测)。
(二)Write Concern
- 默认情况下,Primary完成写操作即返回,Driver可通过设置Write Concern来设置写成功的规则。如设置写必须在大多数节点上成功且超时时间为5s:
javascript
db.products.insert(
{ item: "envelopes", qty : 100, type: "Clasp" },
{ writeConcern: { w: "majority", wtimeout: 5000 } }
)
- 也可以修改副本集默认的write concern,不用每个请求单独设置:
javascript
cfg = rs.conf()
cfg.settings = {}
cfg.settings.getLastErrorDefaults = { w: "majority", wtimeout: 5000 }
rs.reconfig(cfg)
九、复制集性能优化
(一)硬件层面优化
- 存储设备选择:对于复制集节点,尤其是频繁写入的主节点,优先选择高速磁盘,如固态硬盘(SSD)。SSD的随机读写性能远高于传统机械硬盘(HDD),能显著减少写操作的延迟。例如,在高并发写入场景下,使用SSD可将写操作的平均延迟从HDD的十几毫秒降低到1 - 2毫秒。
- 网络配置优化:确保复制集节点之间的网络连接具有低延迟和高带宽。使用千兆以太网或更高速度的网络接口卡(NIC),并且合理规划网络拓扑结构,避免网络拥塞。在跨数据中心部署时,可考虑使用专用网络链路或虚拟专用网络(VPN)来保证数据传输的稳定性和速度。
(二)软件层面优化
- 索引优化 :定期分析查询模式,为频繁查询的字段创建合适的索引。但要注意避免过度索引,因为索引会占用额外的磁盘空间并可能影响写操作性能。可以使用MongoDB的
explain()
命令来分析查询执行计划,确定索引的有效性。例如,如果有一个经常根据用户ID查询用户信息的应用场景,为用户ID字段创建索引可以大大提高查询速度。 - 参数调整 :根据服务器硬件资源和业务负载情况,调整MongoDB的相关参数。例如,
wiredTigerCacheSizeGB
参数可以控制内存中用于缓存数据的大小,合理设置该参数可以提高数据读取性能。同时,maxIncomingConnections
参数可以限制节点接受的最大连接数,防止因过多连接导致服务器资源耗尽。
十、安全相关考虑
(一)身份验证
- 用户管理:为复制集的每个成员配置严格的用户认证机制。创建不同角色的用户,如读写用户、只读用户和管理用户等,并为其分配相应的权限。使用MongoDB的内置身份验证机制,如基于用户名/密码的认证,确保只有授权用户能够访问复制集。例如,为应用程序创建一个只具有读写特定数据库权限的用户,防止该用户对其他数据库进行非法操作。
- 认证协议选择:选择安全可靠的认证协议,如SCRAM - SHA - 256。该协议在传输过程中对密码进行加密处理,相比旧的认证协议更加安全,能有效防止密码泄露和中间人攻击。
(二)数据加密
- 传输加密:在复制集节点之间以及客户端与节点之间启用SSL/TLS加密。通过配置证书和密钥,对网络传输中的数据进行加密,确保数据在传输过程中的机密性和完整性。特别是在跨网络环境(如互联网)部署复制集时,传输加密至关重要。
- 存储加密:对于敏感数据,可以使用MongoDB的加密存储功能。启用企业版的加密存储引擎,对存储在磁盘上的数据进行加密,即使磁盘被盗,数据也不会被轻易窃取。加密存储可以在数据库级别或集合级别进行配置,根据数据的敏感程度灵活选择。
十一、复制集的监控与管理
(一)监控指标
- 系统资源指标 :密切关注节点的CPU使用率、内存使用率、磁盘I/O和网络带宽等系统资源指标。可以使用系统监控工具(如Linux的
top
、iotop
等)以及MongoDB自带的监控命令(如db.serverStatus()
)来获取这些信息。当CPU使用率持续过高时,可能表示查询或写入操作过于频繁,需要优化查询或增加硬件资源。 - 复制相关指标 :重点监控复制集的复制延迟、选举次数、节点状态等指标。通过
db.printSlaveReplicationInfo()
可以查看从节点与主节点之间的复制延迟情况,及时发现并解决复制延迟问题。对于选举次数过多的情况,需要检查网络稳定性、节点健康状况等因素,可能需要调整选举相关的参数。
(二)日常管理操作
- 节点维护:定期对复制集节点进行维护,包括软件更新、硬件检查等。在进行软件更新时,要注意按照正确的升级流程进行,避免因升级导致复制集出现故障。例如,在升级MongoDB版本时,先在从节点上进行升级测试,确保没有问题后再逐步升级主节点和其他从节点。
- 日志管理:妥善管理MongoDB的日志文件,定期清理旧的日志文件,同时设置合适的日志级别。根据需要,可以将日志输出到远程日志服务器,以便集中管理和分析。通过分析日志,可以及时发现复制集运行过程中的异常情况,如节点连接失败、数据同步错误等。