开发者学堂课程【MongoDB 快速入门:复制集使用及原理介绍】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/49/detail/1002
复制集使用及原理介绍(一)
内容介绍:
一、MongoDB副本及概念及创建
二、MongoDB副本集使用介绍
三、MongoDB副本集基本原理介绍
四、课程总结
一、MongoDB 副本及概念及创建
本节课学习mongoDB副本的使用及原理介绍,根据课程分享的大纲,第一部分会学习MongoDB副本及概念及如何创建一个副本作为一个简要的介绍,第二部分是MongoDB副本集的使用方式,第三部分对MongoDB副本集的基本原理进行介绍,比如同步的原理和高可用的原理,第四步分课程总结。首先进行第一部分MongoDB副本集概念及如何去创建一个副本集。
1、什么是 MongoDB 副本集
按照官方的定义来说副本集就是一组MongoDB的进程,同样去维持一份数据集,同样一份数据集是通过MongoDB的复制协议保证组倍之间的数据的一致性的,左边的图有两种部署的方式一个是standalone部署的模式,另外一个就是副本集会有不同角色的节点,像primary节点和secondary节点。生产环境不建议部署standalone模式,后面会去介绍具体的原因。
2、为什么要使用 MongoDB 副本集
有三部分的原因,第一可用性:通过额外的副本结合MongoDB本身高可用机制提升MongoDB实例可用性,第二扩展性:通过secondary节点配合Driver扩展MongoDB实例读能力,第三可维护性:通过滚动的方式对MongoDB做一个维护,尽量减少业务受到的影响,比如版本的升级,可能会影响用户流量的compact的操作,后面会进行实际的演示。
3、MongoDB 副本集成员角色
前面看到副本集里面会有多个节点,每个节点的职责是不一样的,在看具体的成员角色之前,先看两个重要的属性,一个是priority,当priority=0时不可以被副本集选举为主,priority的值越高说明它有更大的可能被选举为主。另一个是votes,当votes=0时不可以参与选举投票,而且如果不能参与选举投票同时priority也必须为0,即它不能被选举为主。角色主要分为三类,一个是primary节点,也就是主节点可以接受读写,整个副本集某个时刻只有一个主节点,另外一个是secondary,被称为只读节点,只读节点分为几个不同的类型,首先是hidden,hidden的属性如果为false说明是正常的只读节点,是否可选为主,可投票,取决于priority,votes的值;如果hidden的值为ture,也就是所谓的隐藏节点,对客户端不可见,可以参与选举,但是priority必须为0,可以参与投票,但是priority必须为0即不能够选举而提升为主。第三个是Delayed Secondary,这个类型的 Secondary和正常的差别较小,唯一的区别就是会延迟一定的时间,这是由slaveDelay的值决定的,从上游复制增量,常用于快速回滚场景。最后是Arbiter节点,即仲裁节点,它是很特殊的,他只参与选举投票,不会被提升为主,本身不承载任何数据。它不会写任何的数据只是用来作为投票的角色。
4、怎样获取 MongoDB 副本集——基于工具搭建测试实例
怎样获取MongoDB副本集也就是怎样创建MongoDB的副本集。首先是基于工具搭建测试实例,目的是业务线下进行测试要在本地环境搭建副本集,或者是探索一些MongoDB新增的功能要去临时搭建一个测试的实例。这里推荐使用mtools工具,这个是MongoDB官方工程师个人作品,虽然不是由官方维护的但是功能也是特别强的,包含实例部署,日志解析/可视化,数据迁移等功能,重点关注实例部署功能,Github:https://github.com/rueckstiess/mtools链接可以去下载和使用。基于mtools部署副本集就是一条命令:mlaunch init--binarypath’/usr/local/Cellar/mongodb-community/4.4.0/bin--replicaset--nodes3--name replset44--dir~/work/mtools_data/data。Mtools一键会将副本集创建好,左边是具体的命令执行的演示,可以自己进行尝试。
5、怎样获取MongoDB副本集--创建云上实例
另外的方式是可以创建云上的实例,MongoDB的运维门槛较高,需要对相关原理有比较深刻的理解才能将MongoDB副本集的实例运维好,推荐一个更可靠更便捷的方式就是使用MongoDB云服务,一站式的解决部署副本集的需求,而且像阿里云的MongoDB具有社区版不具备的高级功能。如左图为阿里云MongoDB的售卖官方页面,点击立即购买就可以创建副本集的实例,下面就是阿里云特有的功能区别于官方的,比如申请日志、申请恢复这是社区版所不具备的。可以点击链接https://www.aliyun.com/products/mongodb。
二、MongoDB 副本集使用介绍
1、MongoDB 副本集连接
首先当有一个MongoDB副本集的时候需要进行连接,连接方式有两种,这里有两个图,一个是方式一直连副本集的primary节点,直接拿着IP port连接,正常情况下是可以读写MongoDB的但是当主节点故障切换后,业务无法进行正常访问。因此强烈建议使用方式二,通过uri高可用的方式连接MongoDB。当primary故障切换后,MongoDBDriver可自动感知并把流量路由到新的primary节点。这里也有详细的连接使用方式,可以看文档:https://help.aliyun.com/document_detail/44623.html。MongoDB也是比较易于用户使用的,在官网的空台上直接就帮用户组装了MongoDB URI的组装格式,直接去复制链接就可以进行使用。
2、MongoDB 副本集状态查看
首先最重要的命令是rs.status命令,它可以查看副本及整体状态,包括各成员当前状态是否健康,是否在全量同步,心跳信息,增量同步信息,选举信息等等,如果发现当前副本集存在问题第一时间应该查看rs.status的输出结果。第二个是db.isMaster查看当前节点角色,它是一个更精简化的信息,除了当前节点角色信息,其他也返回整个副本集的成员列表,真正的primary是谁,协议相关的配置信息等,Driver在首次连接副本集时会发送该命令。第三个是两个命令,一个是rs.printSlaveReplicationInfo,另一个是rs.printReplicationIifo。二者看起来有些像都是和复制相关的,查看同步信息/oplog信息,第一个命令返回一个汇总的secondary同步延迟信息,比如有两个secondary,它们和主页同步延迟的时间是多少秒,第二个是命令返回的oplog大小、保留时长、起始时间等信息。可以去敲一下这个命令看一下。
3、副本集的基本读写
副本集的基本读写是比较简单的,当使用客户端比如说mongo shell是最简单的连接方式,通过mongodb uir 连接副本集实例,执行insert,find,delete等命令,基本上和standalone模式是没有差异的。重点看副本集的读写和standalone模式特意化的地方。第一个就是如何扩展副本集的读能力,就是所谓的readpreference的能力,通过看左图可知,左图是一个三节点的图,实际上是部署在两个数据中心的,primary和其中一个secondary部署在Data Center 1,另外一个secondary部署在Data Center2 。当使用默认的readpreference时是直接去读写primary节点的,假设业务在Data Center也有业务存在也需要读取MongoDB,就需要使用nearest readpreference模式,它能自动地识别节点的远近,然后去读取Data Center的secondary。Readpreference的几种模式,第一种是primary模式,默认模式,直接读取主节点,提供更好的一致性的保证。另外是primarypreferred,它主要区别于primary模式的一个地方是当主节点不可用时,选择从从节点读取。第三个是secondary。只会从从节点读取。第四个是secondarypreferred,尽力从从节点读取,如果找不到可用的从节点,从主节点读。最后一个是nearest模式,它会根据客户端对节点的ping值,然后判断节点的远近,选择从最近的节点读取。Readpreference决定了读请求会访问什么角色的节点。而且合理的readpreference可以极大的扩展副本集的读性能,降低访问延迟。可以合理地使用readpreference。
4、扩展副本集的读能力——readpreference
另一个和副本集相关的读写就是writeConcern,用来控制写操作持久化的级别。writeConcern具体的配置格式包括三个小的参数,一个是w,它决定了写操作返回前需要等待多少个副本集节点的确认,第二个是j,它决定写操作产生的日志是否已经落盘。第三个是wtimeout,决定了写操作等待的超时时间,避免客户端一直阻塞。
5、writeConcern——w:1
下面具体演示writeConcern配置的值,首先w=1的时候,就是说写操作在MongoDB本地执行完之后,直接向客户端返回成功,不需要等待日志也就是wrl 日志journal刷盘,是比较快的。
另外一个是w:1,j:true的时候,区别于w:1的主要特点就是写操作在本地执行完之后,需要等待日志journal刷盘之后,才能向客户端返回成功,也就是会增加额外的延迟。
第三个是w:“majority”,当driver下发一个w:“majority”写操作之后,不仅需要在primary节点上去完成,还需要复制到其中一个secondary节点,进而apply完成,才能向driver返回证明写操作是成功的,在三节点副本集的情况下w:“majority”就是两个节点即w:2 。
6、控制读操作的一致性级别——readConcern
第三个需要关注的是和副本集的读写操作的特性readConcern,用来控制读操作的一致性的级别。readConcern的级别如下:首先是local级别,他表示读操作直接读取本地最新提交的数据,返回的数据可能被回滚。因为比如读取的primary的数据,假设说primary、corcert之后选出了新的组,primary和新的组发生分叉的数据是需要被回滚的,这时实际上说读取到数据后面再进行读取的话是读不到的。第二个级别是available,它的含义和local是比较相似的,但是用在sharding场景可能会返回孤儿文档,sharding在其他课程已经介绍,这里不再做详细介绍。第三个是mojority,它表示读操作返回已经在多数节点确认应用完成的数据,返回的数据不会被回滚,但是他可能会读到一些不是最新的数据即历史的数据。这需要关注。第四个是linearizable的readConcern,他表示读取最新的数据,且能够保证数据不会被回滚,也就是线性一致性,也是最高的一致性级别。最后一个是snapshot,它是用在MongoDB多文档事务中,和mojority语义类似,但额外提供真正的一致性快照语义。MongoDB的事务在其他的课程也有介绍,这里也不做特别详细的分析。
观察三节点的副本集,每一secondary的复制进度是不一样的,是用oplog表示的,比如primary写到了最新x=5,第一个secondary复制到x=4,第二个secondary复制到x=3,在不同的readConcern下,client从不同的节点去读的时候,实际上读到的是不同的版本的数据,对local来说总是读取最新的数据很好理解,available也是读取最新的数据,只是在sharding上行为不太一样。在mojority的情况下,x=4是复制到多数的节点,也就是其中的两个节点,当用majority读的时候,在primary只能读到x=4,在secondary也可以读到x=4,但是在第二个secondary只能读到x=3 。Linearizable也比较特殊,为了维持只能在primary节点上使用Linearizable,所以他也能读取到最新的数据x=5,在这里可能疑惑的地方就是x=5在目前的状态不是majority复制到多数派节点的,这里就是Linearizable读到x=5,在实际的发生过程中会发生等待,会等x=5复制到多数派节点才会向客户端返回成功,这就是对readConcern的介绍。
7、不同 readConcern level 的 tradeoff
对readConcern level的tradeoff不同做一个总结,观察图有三个不同的维,一个是LATEST,就是能读到多新的数据,fast就是能多快的去返回要读的数据。一个是SAFE就是读的数据会不会发生回滚。对于majority来说,它能保证fast和safe的数据不会被回滚,linearizable能保证数据不会被回滚,而且能读到最新的数据,但是其实是它的延迟。Local/available能够最快的返回数据,而且能读到最新的数据,但是数据可能会被回滚。总结,readConcern level越高,一致性保证越好,但访问延迟也更高。
8、基于副本集的维护性操作举例——rollover compact
最后介绍基于副本的可维护性也就是基于副本集的可维护操作,举例rollover compact,首先介绍背景:集合频繁的插入和删除会导致碎片率上升,浪费存储空间。碎片率计算方式的链接:https://developer.aliyun.com/article/769536,可以自己去看碎片率是怎样计算得到的。MongoDB提供compact来解决上述问题就是回收碎片,但compact会阻塞读写对业务是由影响的。在副本模式下,可以基于节点滚动的方式来进行compact操作,避免影响业务。举例假设有一个三节点的副本集,在左边的话可以在hidden节点去做compact collection的操作,hidden是对客户端不可见的,所以这时业务是不受影响的。当在hidden节点做完compact操作会去把当前的secondary切换于hidden,在新的hidden里面去做compact操作,这时对业务也是没有影响的。最后将primary切换于hidden角色,在最后的primary字节上去做compact collection的操作,切换会对业务产生小的影响,比如连接的省略, 当然driver能自动的去hidden这样的事情,所以影响可能就是连接的甩断,完全避免了直接在primary上去做compact,导致业务对DB是不可访问的。以上就是对MongoDB副本集使用的介绍。