52.MongoDB复制(副本)集实战及其原理分析
MongoDB复制集架构
高可用
在生产环境中,不建议使用单机版的MongoDB服务器。
Mongodb复制集(Replication Set)由一组Mongod实例(进程)组成,包含一个Primary节点和多个Secondary节点,Mongodb Driver(客户端)的所有数据都写入Primary,Secondary从Primary同步写入的数据,以保持复制集内所有成员存储相同的数据集,提供数据的高可用。复制集提供冗余和高可用性,是所有生产部署的基础。它的现实依赖于两个方面的功能:
-
数据写入时将数据迅速复制到另一个独立节点上
-
在接受写入的节点发生故障时自动选举出一个新的替代节点
三节点复制集模式
PSS模式(官方推荐模式)
PSS模式由一个主节点和两个备节点所组成,即Primary+Secondary+Secondary。
PSA模式
PSA模式由一个主节点、一个备节点和一个仲裁者节点组成,即Primary+Secondary+Arbiter
安全认证
#mongo.key采用随机算法生成,用作节点内部通信的密钥文件。openssl rand -base64 756 > /data/mongo.key#权限必须是600chmod 600 /data/mongo.key # 启动mongodmongod -f /data/db1/mongod.conf --keyFile /data/mongo.key
复制集连接方式
通过高可用 Uri 的方式连接 MongoDB,当 Primary 故障切换后,MongoDB Driver 可自动感知并把流量路由到新的 Primary 节点
mongosh mongodb://fox:fox@192.168.139.135:27017,192.168.139.136:27017,192.168.139.137:27017/admin?replicaSet=rs0
复制集成员角色
成员角色的属性
Priority = 0 当 Priority 等于 0 时,它不可以被复制集选举为主,Priority 的值越高,则被选举为主的概率更大。通常,在跨机房方式下部署复制集可以使用该特性。假设使用了机房A和机房B,由于主要业务与机房A更近,则可以将机房B的复制集成员Priority设置为0,这样主节点就一定会是A机房的成员。
Vote = 0 不可以参与选举投票,此时该节点的 Priority 也必须为 0,即它也不能被选举为主。由于一个复制集中最多只有7个投票成员,因此多出来的成员则必须将其vote属性值设置为0,即这些成员将无法参与投票。
成员角色
-
Primary:主节点,其接收所有的写请求,然后把修改同步到所有备节点。一个复制集只能有一个主节点。
-
Secondary:备节点,与主节点保持同样的数据集。当主节点“挂掉”时,参与竞选主节点。分为以下三个不同类型:
-
- Hidden = false:正常的只读节点,是否可选为主,是否可投票,取决于 Priority,Vote 的值;
- Hidden = true:隐藏节点,对客户端不可见, 可以参与选举,但是 Priority 必须为 0,即不能被提升为主。 由于隐藏节点不会接受业务访问,因此可通过隐藏节点做一些数据备份、离线计算的任务,这并不会影响整个复制集。
- Delayed :延迟节点,必须同时具备隐藏节点和Priority0的特性,会延迟一定的时间(secondaryDelaySecs 配置决定)从上游复制增量,常用于快速回滚场景。
-
Arbiter:仲裁节点,只用于参与选举投票,本身不承载任何数据,只作为投票角色。比如你部署了2个节点的复制集,1个 Primary,1个Secondary,任意节点宕机,复制集将不能提供服务了(无法选出Primary),这时可以给复制集添加⼀个 Arbiter节点,即使有节点宕机,仍能选出Primary。 Arbiter本身不存储数据,是非常轻量级的服务,当复制集成员为偶数时,最好加入⼀个Arbiter节点,以提升复制集可用性。
#配置隐藏节点
cfg = rs.conf()
cfg.members[1].priority = 0
cfg.members[1].hidden = true
rs.reconfig(cfg)#配置延时节点
cfg = rs.conf()
cfg.members[1].priority = 0
cfg.members[1].hidden = true
#延迟1分钟
cfg.members[1].secondaryDelaySecs = 60
rs.reconfig(cfg)#添加投票节点
# 为仲裁节点创建数据目录,存放配置数据。该目录将不保存数据集
mkdir /data/arb
# 启动仲裁节点,指定数据目录和复制集名称
mongod --port 30000 --dbpath /data/arb --replSet rs0
# 进入mongo shell,添加仲裁节点到复制集
rs.addArb("ip:30000")
# 执行命令
db.adminCommand( {"setDefaultRWConcern" : 1, "defaultWriteConcern" : { "w" : 2 } } )#移除复制集节点
rs.remove("ip:port")
#通过 rs.reconfig() 来移除节点
cfg = rs.conf()
cfg.members.splice(2,1) #从2开始移除1个元素
rs.reconfig(cfg)#更改复制集节点
cfg = rs.conf()
cfg.members[0].host = "ip:port"
rs.reconfig(cfg)
MongoDB复制集原理
数据同步
MongoDB的复制集选举使用Raft算法(https://raft.github.io/)来实现,选举成功的必要条件是大多数投票节点存活。
MongoDB对raft协议添加了一些自己的扩展
- 支持chainingAllowed链式复制,即备节点不只是从主节点上同步数据,还可以选择一个离自己最近(心跳延时最小)的节点来复制数据。
- 增加了预投票阶段,即preVote,这主要是用来避免网络分区时产生Term(任期)值激增的问题
- 支持投票优先级,如果备节点发现自己的优先级比主节点高,则会主动发起投票并尝试成为新的主节点。
一个复制集最多可以有50 个成员,但只有 7 个投票成员。
自动故障转移
一个影响检测机制的因素是心跳,在复制集组建完成之后,各成员节点会开启定时器,持续向其他成员发起心跳,这里涉及的参数为heartbeatIntervalMillis,即心跳间隔时间,默认值是2s。如果心跳成功,则会持续以2s的频率继续发送心跳;如果心跳失败,则会立即重试心跳,一直到心跳恢复成功。
一个影响检测机制的因素是心跳,在复制集组建完成之后,各成员节点会开启定时器,持续向其他成员发起心跳,这里涉及的参数为heartbeatIntervalMillis,即心跳间隔时间,默认值是2s。如果心跳成功,则会持续以2s的频率继续发送心跳;如果心跳失败,则会立即重试心跳,一直到心跳恢复成功。
在electionTimeout任务中触发选举必须要满足以下条件
(1)当前节点是备节点。
(2)当前节点具备选举权限。
(3)在检测周期内仍然没有与主节点心跳成功。
业务影响评估
- 在复制集发生主备节点切换的情况下,会出现短暂的无主节点阶段,此时无法接受业务写操作。
- 对于非常重要的业务,建议在业务层面做一些防护策略,比如设计重试机制。
# MongoDB Drivers 启用可重试写入
mongodb://localhost/?retryWrites=true
# mongo shell
mongosh --retryWrites
如何优雅的重启复制集
- 逐个重启复制集里所有的Secondary节点
- 对Primary发送rs.stepDown()命令,等待primary降级为Secondary
- 重启降级后的Primary
复制集数据同步机制
MongoDB oplog 是 Local 库下的一个集合,用来保存写操作所产生的增量日志(类似于 MySQL 中 的 Binlog)。
primary ---------- write ----------》 local.oplog.rs ---------- read----------》secondary ---------- write ----------》 local.oplog.rs
---------- read----------》secondary ---------- write ----------》 local.oplog.rs
oplog 中的 ts 是备节点实现增量日志同步的关键
每个备节点都分别维护了自己的一个offset,也就是从主节点拉取的最后一条日志的optime,在执行同步时就通过这个optime向主节点的oplog集合发起查询。
MongoDB在4.0版本之后提供了replSetResizeOplog命令,可以实现动态修改oplogSize而不需要重启服务器。
# 将复制集成员的oplog大小修改为60g
db.adminCommand({replSetResizeOplog: 1, size: 60000})
# 查看oplog大小
use local
db.oplog.rs.stats().maxSize
幂等性
某文档x字段当前值为100,用户向Primary发送一条{KaTeX parse error: Expected 'EOF', got '}' at position 12: inc: {x: 1}}̲,记录oplog时会转化为一条…set: {x: 101}的操作,才能保证幂等性。
幂等性的代价 : oplog的写入被放大,导致同步追不上
使用数组时,尽量注意:
- 数组的元素个数不要太多,总的大小也不要太大
- 尽量避免对数组进行更新操作
- 如果一定要更新,尽量只在尾部插入元素,复杂的逻辑可以考虑在业务层面上来支持
复制延迟
为了尽量避免复制延迟带来的风险,我们可以采取一些措施
- 增加oplog的容量大小,并保持对复制窗口的监视。
- 通过一些扩展手段降低主节点的写入速度。
- 优化主备节点之间的网络。
- 避免字段使用太大的数组(可能导致oplog膨胀)。
数据回滚
mongorestore --host 192.168.192:27018 --db test --collection emp -ufox -pfox
--authenticationDatabase=admin rollback/emp_rollback.bson
同步源选择
在settings.chainingAllowed开启的情况下,备节点自动选择一个最近的节点(ping命令时延最小)进行同步。
#默认情况下备节点并不一定会选择主节点进行同步,这个副作用就是会带来延迟的增加,可以通过以下命令关闭
cfg = rs.config()
cfg.settings.chainingAllowed = false
rs.reconfig(cfg)#使用replSetSyncFrom命令临时更改当前节点的同步源
db.adminCommand( { replSetSyncFrom: "hostname:port" })
相关文章:
52.MongoDB复制(副本)集实战及其原理分析
MongoDB复制集架构 高可用 在生产环境中,不建议使用单机版的MongoDB服务器。 Mongodb复制集(Replication Set)由一组Mongod实例(进程)组成,包含一个Primary节点和多个Secondary节点,Mongodb Dr…...

【Unity实战】手戳一个自定义角色换装系统——2d3d通用
文章目录 每篇一句前言素材开始切换头型添加更改颜色随机控制头型和颜色新增眼睛同样的方法配置人物的其他部位设置相同颜色部位全部部位随机绘制UI并添加点击事件通过代码控制点击事件添加颜色修改的事件其他部位效果UI切换添加随机按钮保存角色变更数据跳转场景显示角色数据 …...

ruoyi-nbcio版本从RuoYi-Flowable-Plus迁移过程记录
更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码: https://gitee.com/nbacheng/ruoyi-nbcio 演示地址:RuoYi-Nbcio后台管理系统 从KonBAI / RuoYi-Flowable-Plus 项目移植过来,开始用yarn install之后yarn run dev 还是有问…...

竞赛 深度学习卷积神经网络垃圾分类系统 - 深度学习 神经网络 图像识别 垃圾分类 算法 小程序
文章目录 0 简介1 背景意义2 数据集3 数据探索4 数据增广(数据集补充)5 垃圾图像分类5.1 迁移学习5.1.1 什么是迁移学习?5.1.2 为什么要迁移学习? 5.2 模型选择5.3 训练环境5.3.1 硬件配置5.3.2 软件配置 5.4 训练过程5.5 模型分类效果(PC端) 6 构建垃圾…...

Linux音频-基本概念
文章目录 机器声音的采集原理机器声音的播放原理音频相关基本概念计算机采集音频的模型Linux系统音频框架Linux音频框架的三类角色 Linux音频框架参考文章:Linux音频框架 机器声音的采集原理 声音是一种连续的信号,故其是一种模拟量。 录音设备可以捕获…...
Spring Boot 依赖注入实现原理
Spring Boot 是 Spring 框架的扩展,它简化了 Spring 应用程序的创建和部署。在 Spring Boot 中,依赖注入是实现对象间解耦的重要技术,它使得应用程序的各个组件之间可以通过依赖注入来相互协作,提高了代码的可维护性和可重用性。 …...

cola架构:cola源码中访问者模式应用浅析
目录 1.访问者模式简介 2.cola访问者模式应用 2.1 cola被访问者类图 2.2 cola访问者类图 我们知道,如果一个对象结构包含很多类型的对象,希望对这些对象实施一些依赖其具体类型的操作,但又避免让这些操作“污染”这些对象的类,…...
Openssl数据安全传输平台015:OCCI的使用方法+在项目中的设计与实现
文章目录 1 OCCI使用1.1 初始化 - Environment 类1.2 连接数据库 - Connection 类1.3 执行SQL 2 OCCI在项目中的使用2.1 OCCI单独封装为一个类文件OCCIOP2.2 在ServerOP中作为私有成员2.3 ServerOP::ServerOP(string json)中实例化进行使用2.4 秘钥协商过程中进行读写操作 1 OC…...

ardupilot开发 --- CAN BUS、DroneCAN 、UAVCAN 篇
1. CAN BUS、DroneCAN 、UAVCAN 区别 UAVCAN是一种轻量级协议,旨在通过CAN BUS 在航空航天和机器人应用中实现可靠通信。 UAVCAN网络是分散的对等网络,其中每个对等体(节点)具有唯一的数字标识符 - 节点ID,并且仅需要…...

京东平台数据分析:2023年9月京东空气净化器行业品牌销售排行榜
鲸参谋监测的京东平台9月份空气净化器市场销售数据已出炉! 9月份,空气净化器的销售同比上年增长。根据鲸参谋平台的数据显示,今年9月,京东平台空气净化器的销量将近15万,同比增长约1%;销售额将近2亿元&…...
vue使日历组件点击时间渲染到时间输入框
首先,你需要在 Vue 中创建一个日历组件,该组件应该能够显示一个月的日历并允许用户选择日期。然后,当用户点击一个日期时,你需要将所选日期的值传递给父组件。最后,你可以在父组件中创建一个时间输入框,当用…...

TensorFlow学习:使用官方模型和自己的训练数据进行图片分类
前言 教程来源:清华大佬重讲机器视觉!TensorFlowOpencv:深度学习机器视觉图像处理实战教程,物体检测/缺陷检测/图像识别 注: 这个教程与官网教程有些区别,教程里的api比较旧,核心思想是没有变…...
MATLAB算法实战应用案例精讲-【图像处理】相机标定
目录 知识储备 距离算法和相似度计算方法 1、常见的距离算法 2、常见的相似度(系...

python画气泡标尺图
目录 渐变气泡图彩色气泡图 在进行实验结果分析的时候,气泡标尺图能非常清晰对不同的结果进行多维度的比较,特别是在深度学习模型大小和精度进行比较的时候非常合适使用,以下是几个例子。 渐变气泡图 import seaborn as sns import matplotl…...
Java并发编程指南:如何正确使用信号量和线程池熔断机制
前言: 在分布式系统中,选择合适的熔断机制是保护系统免受故障影响的关键。本文将介绍使用信号量和线程池两种常见的熔断机制,并提供Java和Spring Cloud Alibaba框架下的示例代码,帮助您深入理解和应用。 1. 信号量熔断机制 信号…...

大彩串口屏读写文件问题
分区 本文使用的是大彩串口屏M系列的: 串口屏内部有三个分区,分别为A、B、C三个区: A区:系统区,存储组态工程文件 B区:数据区,存储配置信息,记录数据、历史曲线等 C区:备…...

php之 角色的权限管理(RBAC)详解
RBAC(Role-based access control)是一种常见的权限管理模型,通过将用户分配至特定的角色,以及为角色分配访问权限,实现了权限管理的目的。以下是关于RBAC的详细解释: 角色:RBAC模型的核心是角色…...

asp.net乡村旅游管理系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio
一、源码特点 asp.net乡村旅游管理系统是一套完善的web设计管理系统系统,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为vs2010,数据库为sqlserver2008,使用c# 语言开发 asp.net乡村旅游管理系统 二、…...

【linux】文件系统+软硬连接+动静态库
文件系统软硬连接动静态库 1.理解文件系统1.1磁盘的物理结构1.2磁盘的存储结构1.3磁盘的逻辑结构1.4文件系统 2.软硬链接2.1什么是软硬链接2.2软硬链接的作用 3.动静态库3.1什么是库3.1静态库和静态链接3.2动态库和动态链接3.2.1通过环境变量找到动态库路径3.2.2把动态库拷贝到…...

力扣每日一题73:矩阵置零
题目描述: 给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例 1: 输入:matrix [[1,1,1],[1,0,1],[1,1,1]] 输出:[[1,0,1],[0,0,0],[1,0,1]]示例 2…...

idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...

前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...
GitHub 趋势日报 (2025年06月08日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...