MongoDB系列之副本集Replica Set

勤奋不是嘴上说说而已,而是实际的行动,在勤奋的苦度中持之以恒,永不退却。业精于勤,荒于嬉;行成于思,毁于随。在人生的仕途上,我们毫不迟疑地选择勤奋,她是几乎于世界上一切成就的催产婆。只要我们拥着勤奋去思考,拥着勤奋的手去耕耘,用抱勤奋的心去对待工作,浪迹红尘而坚韧不拔,那么,我们的生命就会绽放火花,让人生的时光更加的闪亮而精彩。

导读:本篇文章讲解 MongoDB系列之副本集Replica Set,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

概述

Replica Set,一般翻译为副本集,RS,是MongoDB官方提供的一个数据及应用高可用解决方案。

RS由2个或更多个节点组成,其中一个用于处理写操作的是主节点(Primary),还有多个用于保存主节点的数据副本的从节点(Secondary)。如果主节点崩溃,则从节点会从其中选取出一个新的主节点。从节点定时通过oplog从主节点复制数据,实现自动failover和recovery。客户端可以从主节点或从节点读取数据,但只能往主节点写数据。

MongoDB支持两种复制的模式:

  • Master Slave,主从复制,角色包括master和slave
  • Replica Set,复制集复制,角色包括primary和secondary

副本集架构图
在这里插入图片描述
RS适用场景:

  • 数据冗余
  • 自动failover,提供高可用性的服务
  • 分散读的负载
  • 简化维护(相对于master-slave来说)
  • 灾难恢复

节点

副本集中的节点主要分为三种:

  • 主节点:Primary,包含所有的写操作的日志。副本服务器集群包含有所有的主服务数据,因此当主服务器挂掉时,就会在副本服务器上重新选取一个成为主服务器。
  • 从节点:Seconary,也叫副本节点,正常情况下,副本集的从节点会参与主节点选举,并从主节点同步最新写入的数据,以保证与主节点存储相同的数据。通常,从节点提供读服务,增加从节点可以提供副本集的读服务能力,同时提升副本集的可用性。
    副本节点可以通过配置指定其具体的属性,比如选举、隐藏、延迟同步等,最多可以有50个副本节点,但只能有7个副本节点能参与选举。
  • 仲裁节点:Arbiter,只参与投票,不能被选举为主节点,并且不从主节点同步数据。当副本集成员为偶数时,最好加入一个仲裁节点,以提升副本集的可用性。当然,如果可以的话,最好使用没有仲裁者的部署。添加额外的仲裁者并不能加快选举速度,也不能提供更好的数据安全性,仅仅能使得副本集成员数为奇数防止选举出现平票。

成员属性

RS的成员具备以下常见属性:

  • priority:对于副本节点,可以通过该属性来增大或减小该节点被选举成为主节点的可能性,取值范围为0-1000(如果是arbiters,则取值只有0或1),数据越大,成为主节点的可能性越大,如果被配置为0,就不能被选举成为主节点,也不能主动发起选举。
    这种特性一般会被用在有多个数据中心的情况下,如一个主数据中心,一个备份数据中心,主数据中心速度会更快,如果主节点挂掉,希望新主节点也在主数据中心产生,就可以设置在备份数据中心的副本节点优先级为0
  • hidden:隐藏节点会从主节点同步数据,但对客户端不可见,在mongo shell 执行db.isMaster()方法也不会展示该节点,隐藏节点Priority必须为0,即不可以被选举成为主节点。但是如果有配置选举权限的话,可以参与选举。
    隐藏节点对客户端不可见,跟客户端不会互相影响,可以用来备份数据或者跑一些后端定时任务之类的操作
  • slaveDelay:延迟同步即延迟从主节点同步数据,如延迟时间配置1小时,现在时间是 09:52,那么延迟节点中只同步到主节点 08:52 之前的数据。延迟节点必须是隐藏节点,且Priority为0。
    为了防止数据库误操作,比如更新服务前,一般会先执行数据库更新脚本,如果脚本有问题,且操作前未做备份,那数据可能就找不回。但如果说配置延迟节点,那误操作完,还有该节点可以兜底。
  • tags:支持对副本集成员打标签,在查询数据时会用到,如找到对应标签的副本节点,然后从该节点读取数据,可以根据标签对节点分类,查询数据时不同服务的客户端指定其对应的标签的节点,对某个标签的节点数量进行增加或减少,也不怕会影响到使用其他标签的服务。
  • votes:表示节点是否有权限参与选举,最大可以配置7个副本节点参与选举。

成员类型

包括被动成员和隐藏成员:

  • 被动成员
    给从节点设置 priority 可以指定其成为主节点的优先级,取值范围是 0 到 100,默认是1。
    优先级为 0 的从节点不参与选举,这样的从节点被称为被动成员。
    拥有最高优先级的成员总是会被选举为主节点(只要它能连接到副本集中的大多数成员,并且拥有最新的数据)。
  • 隐藏成员
    给从节点设置 hidden 为 true 可以将其作为隐藏成员,隐藏成员只对 isMaster 不可见。
    客户端不会向隐藏成员发送请求,隐藏成员也不会优先作为副本集的数据源(尽管当其他复制源不可用时隐藏成员也会被使用)。
    通常会将性能较弱的服务器或者备份服务器隐藏起来,因此,隐藏成员适合做数据备份、离线计算的任务。

成员状态

成员之间通过心跳来传达自己的状态。最常见的状态就是“主节点”和“从节点”状态,其他状态:

  • STARTUP: 成员在第一次启动时的状态,正在尝试加载副本集配置
  • STARTUP2: 配置被加载后进入这个状态,初始化同步过程会持续处于这个状态
  • RECOVERING: 成员运行正常,但不能处理读请求
  • ARBITER: 仲裁节点独有的特殊状态
  • DOWN: 一个成员被正常启动,但后来变为不可访问
  • UNKNOWN: 如果一个成员未能访问到另一个成员,那么就不知道它处于什么状态
  • REMOVED: 此成员已被从副本集中移除
  • ROLLBACK: 成员正在回滚数据中会处于此状态

实战

部署

通过k8s部署副本集
MongoDB系列之副本集Replica Set
该配置中描述的资源:
◈ 从核心开始,有一个名为 mongo-node1 的容器。 mongo-node1 包含一个名为 mongo 的镜像,这是一个在 Docker Hub [5] 上托管的一个公开可用的 MongoDB 容器镜像。容器在集群中暴露端口 27107。
◈ Kubernetes 的数据卷功能用于将连接器中的 /data/db 目录映射到名为 mongo-persistent-storage1 的永久存储上,这又被映射到在 Google Cloud 中创建的名为 mongodb-disk1 的磁盘中。这是 MongoDB 存储其数据的地方,这样它可以在容器重新编排后保留。
◈ 容器保存在一个 pod 中,该 pod 中有标签命名为 mongo-node,并提供一个名为 rod 的(任意)示例。
◈ 配置 mongo-node1 复制控制器以确保 mongo-node1 pod 的单个实例始终运行。
◈ 名为 mongo-svc-a 的 负载均衡 服务给外部开放了一个 IP 地址以及 27017 端口,它被映射到容器相同的端口号上。该服务使用选择器来匹配 pod 标签来确定正确的 pod。外部 IP 地址和端口将用于应用程序以及副本集成员之间的通信。每个容器也有本地 IP 地址,但是当容器移动或重新启动时,这些 IP 地址会变化,因此不会用于副本集。

添加节点

副本集数据量比较大时如何添加次节点
当副本集的数据量比较大时,添加新节点时,如果使用初始化同步的话,会给主节点造成比较大的压力。有以下选择:

  • 暂停当前副本集中的一个次节点,然后将 次节点的数据(data)复制到要新添加的节点的数据目录。然后再将两个节点启动。(建议先测试)
    如果要复制数据文件,请确保您的副本包含local数据库的内容。
  • 指定同步节点 rs.syncFrom(hostportstr),指定同步节点为次节点,默认的是同步节点 是主节点。
    但是该设置在重新启动节点,或者同步指定的新节点的连接被关闭了,是会失效的。(建议先测试)

选举

触发时机
当出现以下情况时,会触发选举机制:

  • 初始化副本集时
  • 往副本集中新加入节点
  • 对副本集进行维护时,如执行rs.stepDown()rs.reconfig()操作时
  • 从节点失联时,如超时(默认是10秒)

以下因素会影响到选举结果:

  • 副本集的选举协议
  • 心跳
  • 成员权重
  • 数据中心失联
  • 网络分区
  • 镜像读取

故障转移回滚
回滚指的是,当成员在故障转移后重新加入其副本集时,将还原之前主节点上的写操作,并恢复成现在主节点的状态数据。

仅当节点接收到主节点降级前未成功复制的写操作后,重新加入副本集群之后发现与现有主节点的数据不一致时,才需要回滚。

当节点重新加入到副本集群时,它会还原或“回滚”其不一致的写操作,以保持与其他成员的一致性。

写关注

Write concern,指写入一条数据,主节点处理完成后,需要其他承载数据的副本节点也确认写成功后,才能给客户端返回写入数据成功。
这个功能主要是解决主节点挂掉后,数据还未来得及同步到副本节点,而导致数据丢失的问题。

可以配置节点个数,默认配置{"w": 1},表示主节点写入数据成功,即可给客户端返回成功;{"w": 2},表示除主节点,还需要收到其中一个副本节点返回写入成功,才能给客户端返回成功;{"w": majority},表示需要集群中大多数承载数据且有选举权限的节点返回写入成功。

在写请求中指定 writeConcern 相关参数:

db.products.insert(
    { item: "envelopes", qty: 100, type: "Clasp" },
    { writeConcern: { w: "majority", wtimeout: 5000 } }
)

修改副本集 getLastErrorDefaults 配置:

cfg = rs.conf()
cfg.settings.getLastErrorDefaults = { w: "majority", wtimeout: 5000 }
rs.reconfig(cfg)

读偏好

Read preference,为了保持一致性,写只能通过主节点,但读可以选择主节点,也可以选择副本节点,区别是主节点数据最新,副本节点因为同步问题可能会有延迟,但从副本节点读取数据可以分散对主节点的压力。

读写模式

默认情况下,副本集的所有读请求都发送到主节点,Driver 可通过设置 Read Preference 来将请求路由到其他节点,规则如下:

  • primary:默认规则,所有读请求发送到主节点
  • primaryPreferred:主节点优先,如果主节点不可达,请求从节点
  • secondary:所有读请求发送到从节点
  • secondaryPreferred:从节点优先,当所有从节点不可达时请求主节点
  • nearest:读请求发送到最近的可达节点上(通过 ping 探测得出最近的节点)

3个条件,条件是在符合模式的基础上,再根据条件删选具体的节点

  • Tag Sets(标签)
    这个可以给节点加上标签,然后查找数据时,可以根据标签选择对应的节点,然后在该节点查找数据。可通过mongo shell 使用rs.conf()查看当前每个节点下面的 tags, 修改或添加tags 过程同上面修改 getLastErrorDefaults 配置 ,如:cfg.members[n].tags = { "region": "South", "datacenter": "A" }
  • maxStalenessSeconds (可容忍的最大同步延迟)
    这个值是指副本节点同步主节点写入的时间 跟 主节点实际最近写入时间的对比值,如果主节点挂掉了,那就跟副本集中最新写入的时间做对比。
    建议设置,避免因为部分副本节点网络原因导致比较长时间未同步主节点数据,然后读到比较老的数据。该值需要设置 90s 以上,因为客户端是定时去校验副本节点的同步延迟时间,数据不会特别准确,设置比 90s 小,会抛出异常。
  • Hedged Read (对冲读取)
    MongoDB 4.4 版本后才支持,指 mongos 实例路由读取请求时会同时发给两个符合条件的副本集节点,然后那个先返回结果就返回这个结果给客户端。

使用connection string uri时,可加上以下三个参数:

  • readPreference,枚举值:primary、 primaryPreferred、secondary、secondaryPreferred、nearest
  • maxStalenessSeconds,最大同步延时秒数,取值0 – 90会报错, -1 表示没有最大值
  • readPreferenceTags 标签,如果标签是{ "dc": "ny", "rack": "r1" },则在uri 为 readPreferenceTags=dc:ny,rack:r1

在mogo shell 中,可使用cursor.readPref()Mongo.setReadPref()cursor.readPref()参数分别为:mode、tag set、hedge options,例如:

db.collection.find({}).readPref(
    "secondary",                      // mode
    [ { "datacenter": "B" },  { } ],  // tag set
    { enabled: true }                 // hedge options
)

Mongo.setReadPref()类似,预先设置请求条件,这样就不用每个请求后面带上 readPref 条件。

命令

MongoDB提供RS方法:

  • rs.help():查看帮助
  • rs.initiate():初始化
  • rs.conf():查看当前的配置
  • rs.reconfig():需找到primary主机,在该主节点服务器上才有权限修改配置
  • rs.add('ip:port'):添加节点
  • rs.addArb('ip:port'):添加仲裁节点
  • rs.remove('ip:port'):移除节点
  • rs.status():查看各个节点状态和身份
  • rs.slaveOk():次节点执行,表示允许次节点读取数据
  • rs.freeze(secs):设定某个节点多少秒不可成为主节点
  • rs.isMaster():判断当前节点是否是主节点
  • rs.syncFrom(hostportstr):设置次节点从指定节点同步数据
  • rs.stepDown([stepdownSecs, catchUpSecs]):降低主节点为次节点,只能在主节点上运行,进而触发选举
  • rs.printReplicationInfo():以主节点的视角打印RS集群信息
  • rs.printSecondaryReplicationInfo():以从节点的视角打印RS集群信息
  • rs.printSlaveReplicationInfo():自版本4.4.1后已废弃,使用rs.printSecondaryReplicationInfo()
  • rs.reconfigForPSASet()
    MongoDB提供的与RS相关的DB方法
  • db.printSlaveReplicationInfo():查看副本集的次节点与主节点延迟

参考

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/142078.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!