11.MongoDB系列之连接副本集与副本集管理

1. 副本集组成

1.1 同步

复制是指多台服务器保持相同的数据副本。MongoDB通过保存操作日志(oplog)实现复制功能。
oplog存在于主节点local数据库中的一个固定集合,包含了主节点执行的每一次写操作。
每个节点维护自己的oplog,用来记录它从主节点复制的每个操作,从节点停止运行重启后,会从oplog中的最后一个操作开始同步,openlog中的每个操作都是幂等的,所以目标数据集执行一次与多次都会产生同样的效果。
由于openlog大小固定,因此只能容纳一定数量的操作。在大多数情况下,默认的oplog大小就足够了。但以下的工作负载可能会需更大的oplog。

  • 一次更新多个文档
    为了保持幂等性,oplog必须将多文档更新转换为多个单独的操作
  • 删除的数据量与插入的数据量相同
    此情况下,磁盘使用量不会增加,但是操作日志可能会非常大,因为删除与插入都要一条条记录操作日志
  • 大量的就地(in-place更新)
    如果很大一部分工作负载是不增加文档大小的更新,那么也会有大量操作日志

mongodb中存在两种形式数据同步:初始化同步 与 复制

1.2 初始化同步

初始化同步用于向新成员添加完整的数据集。
当一个副本集启动时,它会检查自身的有效状态,如果有效,则会从副本集的另一个成员中复制完整副本。

首先,MongoDB会将现有数据全部删除,然后克隆除local数据库之外的所有数据库。一但所有的数据库都被克隆,mongod会检查同步源的oplog,将在复制过程中发生的所有变更应用到数据集上。

有个特别注意的问题是初始化同步时间过长。这种情况下, 新成员可能从同步源oplog末尾脱离(毕竟它是固定集合),导致永远无法跟上同步源。除了在不太忙的时候初始化,别无他法。

1.3 复制

从节点会在初始化同步后持续复制数据。它们从同步源复制oplog,并在一个异步进程中应用这些操作。

1.4 成员状态

  • STARTUP
    成员第一次启动时的状态,这是MongoDB尝试加载副本集配置

  • STARTUP2
    配置被加载,处于初始化同步状态,通常只需几秒。

  • RECOVERING
    此状态表明成员运行正常,但不能处理读请求

  • ARBITER
    仲裁者独有的状态

  • DOWN UNKNOW REMOVED
    表示系统处于异常状态

2. 连接副本集

2.1 Python连接副本集

from pymongo import MongoClient
from bson.codec_options import CodecOptions
from retry import retry
import pytz
import pandas as pd


class MongoDbClient:

    def __init__(self, uri):
        self.mongoClient = MongoClient(uri)

    @retry(tries=1, delay=5)
    def get_collection(self, db, collection):
        return self.mongoClient.get_database(db).get_collection(collection) \
            .with_options(codec_options=CodecOptions(tz_aware=True, tzinfo=pytz.timezone('Asia/Shanghai')))

MONGO_CLIENT = MongoDbClient("mongodb://127.0.0.1:27019/?connectTimeoutMS=60000&socketTimeoutMS=10000000")

students_conn = MONGO_CLIENT.get_collection('study', 'students')

df = pd.DataFrame(list(students_conn.find({}).batch_size(1000)))
print(len(df))

2.2 写入时等待复制

db.students.insertOne({'username': 'liuyifei'}, {writeConcern: {'w': 'majority', 'wtimeout': 100}})

通过majority,只有写操作被复制到副本集中大多数成员后,服务器才会进行响应

{
    "acknowledged": true,
    "insertedId": ObjectId("62cd861c01440000150028d4")
}

2.3 自定义复制保证规则

var config = rs.config()
// 设置节点标签表示北京、上海数据中心
config.members[0].tags = {"dc": "sh"}
config.members[1].tags = {"dc": "sh"}
config.members[2].tags = {"dc": "bj"}
// 第一次时设置{}
config.settings = {} 
// 2表示在2个分组中,每组至少写入一台服务器
config.settings.getLastErrorModes={"eachDc": {"dc": 2}}
rs.reconfig(config)

现在可以在可操作中应用这条规则

db.students.insertOne({'username': 'liuyan'}, {writeConcern: {'w': 'eachDc', 'wtimeout': 100}})

2.4 将读请求发送到从节点

默认情况下,驱动程序会将所有请求路由到主节点。但某些情况下从节点读取还是有意义的。

2.4.1 一致性考虑

对一致性读取要求非常高的应用程序不应该从从节点读取数据。若不高可以考虑

2.4.2 负载考虑

当为了从节点承担系统的负载时,可以考虑从节点读取。

2.4.3 由从节点读取数据的场景

当主节点发生故障仍然希望能够执行读操作。当失去主节点时,副本集会进入一个临时的只读模式。这种读偏好叫做primaryPreferred.

如果从节点可用,则读偏好secondary总是将读请求发送给从节点,没有可用从节点,则会出现错误,不会将读请求发送给主节点,而读偏好secondaryPreferred也将读请求发送给从节点,但没有可用从节点时会将请求发送给主节点

应该根据应用程序的需求来考虑哪些选项更合适。

  • 如果读请求必须从主节点读取数据,则使用primary
  • 如果读请求不要求数据是最新的,则使用primaryPreferred
  • 如果读请求低延迟需求大过一致性需求,则使用nearest

3. 副本集管理

3.1 控制成员状态

3.1.1 把主节点变为从节点

rs.stepDown()

3.1.2 阻止选举

如果需要对主节点维护,不想期间其他从节点选举为主节点,则可以

rs.freeze(10000)

维护完成后,只需要再次执行以下命令即可

rs.freeze(0)

3.2 监控复制

3.2.1 获取状态

rs.status()

3.2.2 可视化复制图谱

> server1.adminCommand({replSetGetStatus:1})['syncingTo']
server0:27017

表示server0是server1的复制源。

MongoDB会根据ping的时间会选择同步源。MongoDB维护着心跳时间的滑动平均值,当其选择同步源的时候,它会查找离它最近并且数据比它新的成员。因此自动复制链不会出现复制循环的问题

自动复制链的缺点是:更多复制链意味着复制需要更长的时间,最差情况复制路径会变为一条线A->B->C,当然可以通过以下命令自定义同步源:

secondary.adminCommand({'replSetSyncFrom': 'server0:27017'})

3.2.3 复制循环

由2.2可知,自定义同步源可能出现复制循环的问题,所以需要rs.status()仔细检查

3.2.4 禁用复制链

链式复制是指一个从节点从另一个从节点(而不是主节点)进行同步,可以通过如下操作实现强制每个成员从主节点同步(如果主节点不可用,则会从从节点进行同步)

var config = rs.config()
config.settings = config.settings || {}
config.settings.chainingAllowed = false
re.reconfig(config)

3.2.5 计算延迟

// 给出了主节点oplog的简要信息,包括大小和操作的日期范围
rs.printReplicationInfo()
// 获取每个成员的syncedTo值及最后一条oplog写入每个从节点的时间
rs.printSalveReplicationInfo()

3.2.6 调整oplog大小

// 检查oplog的当前大小,已MB显示集合大小
> user local
> db.oplog.rs.stats(1024*1024).maxSize
// 更改oplog大小为16G
> db.adminCommand({replSetResizeOplog: 1, size: 16000})

一般情况下,不应减少oplog的大小,毕竟只是占用磁盘空间,并且可以防止复制末尾脱节问题。
欢迎关注公众号算法小生或沈健的技术博客shenjian.online

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

算法小生Đ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值