11.MongoDB之副本集与Oplog

这篇文章主要介绍MongoDB副本集相关知识,后续会不断完善。

1、副本集组成与简介

所以副本集就是同一份数据冗余存储,通常用于高可用性的保证。如下图为MongoDB副本集的架构图:

(1)副本集是维护相同数据集的一组mongod实例(mongod:一台部署mongodb的机器实例)

(2)MongoDB副本集组成。一个副本集包含多个数据承载节点(data bearing node)和一个仲裁器节点(可选)。在数据承载节点中有一个且只有一个成员被视为主节点,而其他节点被视为次节点。仲裁器节点不承载数据主要用于选举。仲裁节点永远是仲裁节点,但是主节点可能因选举变成副节点,副节点也有可能因选举而变成主节点。

(3)冗余与高可用。副本集的作用就是通过冗余来保证高可用。通过冗余存储,副本集整体对单个节点不可用提供具有一定的容忍性;

(4)副本集的另一个功能是通过配置读写策略可以是实现读扩展(读写策略处介绍)

(5)副本集中主节点接收所有写入操作。主节点会通过操作日志(oplog)记录所有数据集的更改操作(mongodbprimary节点写数据时也会将oplog写到primary节点所在的local数据库中)

注:写请求都是直接打到主节点的,虽然从节点也要去复制数据;即使这样,主节点要做的事情还是要比从节点多很多。也就是说主节点的cpu占用比副节点高是正常现象。

2、副本集心跳分析

         MongoDB副本集成员之间通过心跳感知其他节点的存活状态。副本集成员一般情况下每2秒钟彼此之间发送一次心跳,就是我们通常说的ping。通常节点超过10S没人任何反馈就会被标记位不可用。如果这个超过10s没有响应的节点为主节点,这个时候副节点就会触发选举重新投票选出主节点实现自动故障转移。

相关代码主要集中在:

mongo/db/repl/replication_coordinator_impl_heartbeat.cpp

mongo/src/mongo/db/repl/replication_coordinator_impl.cpp

副本集最重要的三个关键点,分别是:①数据同步 ②故障转移 ③配置读选项。

1、数据同步

为了维护分片数据集的最新副本,副本集的secondary节点将同步或复制来自其他成员的数据。MongoDB使用两种形式的数据同步:一个是初始化同步,即用完整的数据集填充新成员;另一个是借助oplog的实时变更的同步。

1.1、初始化同步

关于初始化同步这里就不做过多介绍,其实就是完整的copy。

1.2、实时同步

关于Oplog的官网说明 : Replica Set Oplog — MongoDB Manual

1、Oplog简介。Oplog即操作日志(operation log)是用于保存Mongodb数据库所有数据操作记录(实际上只记录改动数据库数据的操作记录,即增/删/改)的固定大小集合(Capped Collections)。类比过来的话就相当于是mysql的binlog日志。

Oplog的存在及大地方便了MongoDB副本集的各节点的数据同步。

2、副本集数据同步的过程。

其流程大概如下:Primary节点写入数据后,Secondary节点为了保证自身数据足够新会检查自己local数据库的oplogt.rs集合,找出最近的一条记录的时间戳;接着会去查询Pirmaryoplog.rs集合找出所有大于此时间戳的记录;之后再将操作记录写到自己的oplog执行这些记录所代表的操作①所有的副本集成员都会有一个oplog的副本 ②oplog中的每次操作都是幂等的,即便有操作被同步了两次或多次也不会有什么负面影响。③为了提高复制效率,副本集中的所有节点之间会相互的进行心跳检测(ping),每个节点都可以从其他节点获取oplog。④mongodb将oplog.rs设置成一个capped类型的集合即固定大小,这符合情理;⑤但是对于长时间宕机的节点secondary节点利用自己最新的时间戳去查找primary节点的oplog.rs时会出现找不到的情况,此时不得不手动重新同步数据了。⑥由此可见oplog的大小非常重要。

注:对于固定集合(Capped Collections)就把他想成一个环形队列,当集合空间用完后,再插入元素就会覆盖最初始的头部元素。

主从同步有很多自己的细节。但是总的来讲拉取oplog并回放可以理解为“单个生产者多个消费者”的生产者-消费者模型。彼此是独立的,正常情况下相互也是不阻塞的。关于代码细节,有机会研究下吧。

1.3、同步延迟分析

       问题:当负载过大时mongodb的主从同步存在明显延迟,导致有时候读取不到最新的数据。

        正常使用场景这种延迟几乎是感知不到的,例如自己手动测试的时候完全不会出现数据不一致的情况、另外腾讯云的主从延迟监控也都远远在秒级以下(可能仅ms量级)。但是如果写入负载特别大的情况下可能就会出现较为明显的延迟,不过就我们50k/min的写入量几乎没出现过明显延迟的。关于这一点也不是mongodb的问题,因为CAP理论决定了一致性、可用性和分区容忍性只能32,对于大多数据分布式数据库来说都是选择A(可用性)P(分区容忍性)放弃C(一致性),转而追求要求不那么高的最终一致性。

注:CAP理论中的C(一致性)指的是线性一致性(强一致性),与之对应的是最终一致性(弱一致性)。

        除了主从不同方面的数据一致性以外,mongodb还有数据读写方面的一致性、以及内存/磁盘维度的数据一致性等。感觉可以专门讲一讲。

3、Oplog的默认大小

当你首次启动副本集成员的时候,如果你没有指定oplog的打下,mongodb会自动创建一个默认大小的oplog。对于Unix 和Windows系统,默认oplog的大小取决于引擎,如下:

Storage Engine Default Oplog Size Lower Bound Upper Bound
In-Memory 5% of physical memory 50 MB 50 GB
WiredTiger 5% of free disk space 990 MB 50 GB
MMAPv1 5% of free disk space 990 MB 50 GB

在大多数情况下,默认的oplog大小是足够用的。例如,如果oplog占可用磁盘空间的5%,并在24小时的操作中填满,则副本节点可以实现24小时不从oplog复制数据也不会影响最终同步(例如副本节点宕机)。大多数副本集的操作量要小得多,它们的oplog可以容纳更多的操作。

通常系统中存在以下操作的话,可能就需要设置更大的Oplog值来避免数据的丢失。

①一次性更新大量数据 ②删除域插入大致同样数量的数据 ③大量的更新现有数据

4、oplog常用命令

(1)查看oplog的状态:

rs.printReplicationInfo()

(2)查看oplog存储设置的大小

use local

db.oplog.rs.stats().maxSize

(3)查看oplog最大大小和现在占用大小以及记录时长

db.getReplicationInfo()

(4)更改副本集成员的Oplog大小  

db.adminCommand({replSetResizeOplog: 1, size: 15000})

注意点:

(1)sharding架构下,mongos不能查看oplog,但是我们可以到每个mongod实例去看。

另外,上面诸多命令在单mongo实例下也是不能用的(提示没有探测到副本集)。

 

与之类似的玩法:

redis中的玩法:

其实这个玩法和redis的AOF持久化完全就是一个思想,AOF持久化就是以日志的形式记录服务器所处理的数据改动操作,记录下来;万一redis挂了进行数据恢复的时候就先恢复RDB持久化下来的二进制压缩存储,然后以之为契机重现一遍写 增、删、改操作即可。

mysql中的玩法:

MySQL 的二进制日志 binlog 可以说是 MySQL 最重要的日志,它记录了所有的 DDL 和 DML 语句(除了数据查询语句select、show等),以事件形式记录,还包含语句所执行的消耗的时间,MySQL的二进制日志是事务安全型的。binlog 的主要目的是复制和恢复。Binlog日志的两个最重要的使用场景
①MySQL主从复制:MySQL Replication在Master端开启binlog,Master把它的二进制日志传递给slaves来达到master-slave数据一致的目的
②数据恢复:通过使用 mysqlbinlog工具来使恢复数据

2、故障转移

3、配置读选项

猜你喜欢

转载自blog.csdn.net/mijichui2153/article/details/118944699