MongoDB副本集其他细节
副本集环境的搭建以及一些基本的操作我们都了解了,本文我们来看看这个数据复制到底是怎么实现的。
数据同步方式
MongoDB中的复制功能主要是使用操作日志oplog.rs来实现的,oplog.rs包含了主节点的每一次写操作,oplog.rs是主节点中local数据库的一个固定集合,我们可以通过如下命令查看到:
use local
show tables
如下:
备份节点通过查询这个集合就知道要复制哪些数据,同时,每一个备份节点也都维护着自己的oplog.rs,自己的oplog.rs则用来记录每一次从主节点复制数据的操作,如此,每一个备份节点都可以再作为数据源提供给其他成员使用,如果某一个备份节点在使用的过程中挂掉了,那么当它重启之后,会自动从oplog.rs的最后一个操作开始同步。
上文我们也已经说过oplog.rs是一个固定集合,我们可以通过db.getCollection('oplog.rs').stats()
这个命令来查看这个固定集合的属性,包括集合大小等,执行部分结果如下:
{
"ns" : "local.oplog.rs",
"size" : 18170305,
"count" : 177443,
"avgObjSize" : 102,
"storageSize" : 5902336,
"capped" : true,
"max" : -1,
"maxSize" : 1038090240,
"sleepCount" : 0,
"sleepMS" : 0,
}
既然是固定集合,它里边能够保存的数据大小就是有限的。通常,oplog.rs使用空间的增长速度与系统处理处理写请求的速率近乎相同,比如主节点每分钟处理了1KB的写入请求,那么oplog.rs也可能会在一分钟内写入1KB条操作日志,但是如果主节点执行了批量删除的命令,比如下面这种:
db.c1.deleteMany({x:{$type:1}})
此时每一个受影响的文档都会产生一条oplog中的日志,这个时候oplog.rs中的日志会快速增加。
成员状态
到目前为止我们了解到的成员状态有两种,一个是PRIMARY,还有一个是SECONDDARY,成员状态的获取需要靠心跳来维护,副本集中的每一个成员每隔两秒就会向其他成员发送一个心跳请求,用来检查成员的状态,成员的状态主要有如下几种:
STARTUP
副本集中的成员刚刚启动时处于这个状态下,此时,MongoDB会去加载成员的副本集配置,配置加载成功之后,就进入到STARTUP2的状态。
STARTUP2
整个初始化同步过程都处于这个状态。
RECOVERING
这个状态是由STARTUP2状态来的,此时成员运转正常,但是此时还不能处理读取请求。
ARBITER
这是仲裁者所处的状态。
DOWN
当一个原本运行正常的成员无法访问到时,该成员就处于DOWN的状态。
UNKNOWN
如果一个成员无法到达其他任何成员,该成员就处于UNKNOWN状态,比如我们利用rs.add()方法添加一个不存在的成员,这个成员的状态就是UNKNOWN。
REMOVED
成员被从副本集中移除时就变成这个状态。
ROLLBACK
如果成员正在进行数据回滚,它就处于ROLLBACK状态,回滚结束后会转换为RECOVERING状态。
FATAL
当一个成员发生了不可挽回的错误时,且不再尝试恢复正常的话,就处于这个状态。
主节点转备份节点
通过如下命令可以让主节点转为备份节点:
rs.stepDown()
主节点转为备份节点之后会有新的主节点被选举出来,可以通过rs.status()来查看新的主节点。
rs.status()方法
前面我们已经多次使用过rs.status()方法,rs.status()方法会列出每个备份节点的含义,我们来看看这些参数的含义,先来列出一个rs.status()方法的返回值样例:
{
"members" : [
{
"_id" : 1,
"name" : "192.168.248.135:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 241,
"optime" : {
"ts" : Timestamp(1509881297, 1),
"t" : NumberLong(16)
},
"optimeDurable" : {
"ts" : Timestamp(1509881297, 1),
"t" : NumberLong(16)
},
"optimeDate" : ISODate("2017-11-05T11:28:17Z"),
"optimeDurableDate" : ISODate("2017-11-05T11:28:17Z"),
"lastHeartbeat" : ISODate("2017-11-05T11:28:18.073Z"),
"lastHeartbeatRecv" : ISODate("2017-11-05T11:28:18.769Z"),
"pingMs" : NumberLong(0),
"syncingTo" : "192.168.248.136:27017",
"configVersion" : 15
},
{
"_id" : 3,
"name" : "192.168.248.136:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 250,
"optime" : {
"ts" : Timestamp(1509881297, 1),
"t" : NumberLong(16)
},
"optimeDate" : ISODate("2017-11-05T11:28:17Z"),
"electionTime" : Timestamp(1509881276, 1),
"electionDate" : ISODate("2017-11-05T11:27:56Z"),
"configVersion" : 15,
"self" : true
}
]
}
1.stateStr用来描述当前节点的状态。 2.uptime表示从成员可达到现在所经历的时间。 3.optimeDate表示每个成员的oplog中最后一个操作发生的时间。 4.lastHeartbeat表示当前服务器最后一次收到其他成员心跳的时间。 5.pingMs表示心跳从当前服务器到达某个成员所花费的平均时间。 6.syncingTo表示同步的数据源。 7.health表示该服务器是否可达,1表示可达,0表示不可达。
复制链问题
数据复制时可以从主节点直接复制,也可以从备份节点开始复制,从备份节点复制可以形成复制链,如果想禁止复制链,即所有的数据都从主节点复制,可以通过chainingAllowed属性来设置,具体步骤如下:
config=rs.config()
config.settings.chainingAllowed=false
rs.reconfig(config)
好了,MongoDB中副本集的其他细节我们就先说到这里,小伙伴们有问题欢迎留言讨论。
参考资料:
1.《MongoDB权威指南第2版》
- .net采集网页方法大全(5种)
- C#+HtmlAgilityPack+XPath带你采集数据(以采集天气数据为例子)
- 中文分词之结巴分词~~~附使用场景+demo(net)
- 用微信二维码登录自己的网站
- 2620: [Usaco2012 Mar]Haybale Restacking
- 1671: [Usaco2005 Dec]Knights of Ni 骑士
- 1592: [Usaco2008 Feb]Making the Grade 路面修整
- Mysql 该如何 Entity Framework 数据库迁移 和 如何更好的支持EF.Extended
- 1734: [Usaco2005 feb]Aggressive cows 愤怒的牛
- 高性能替代反射调用的几种方式
- 1596: [Usaco2008 Jan]电话网络
- 1589: [Usaco2008 Dec]Trick or Treat on the Farm 采集糖果
- 1647: [Usaco2007 Open]Fliptile 翻格子游戏
- 1295: [SCOI2009]最长距离
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- JavaWeb第二讲 重定向与转发 & doGet()与doPost()
- JavaWeb第一讲 Servlet的工作原理及生命周期
- 多系列数据核密度图
- leetcode树之二叉树的层平均值
- 大型项目技术栈第二讲 ES6(ECMAScript 6.0)的使用
- 大型项目技术栈第三讲 ztree的使用
- JavaWeb新手训练经典项目 & 半小时高效开发 & 海量知识点涵盖 = 从这里开始
- Java反射_笔记分享
- Java注解详细总结
- 文档驱动 —— 表单组件(六):基于AntDV的Form表单的封装,目标还是不写代码
- 这就是你日日夜夜想要的docker!!!---------Docker资源控制--Cgroup
- 2020-09-26:请问rust中的&和c++中的&有哪些区别?
- python在Keras中使用LSTM解决序列问题
- python使用MongoDB,Seaborn和Matplotlib文本分析和可视化API数据
- 用于NLP的Python:使用Keras进行深度学习文本生成