千家信息网

Mongodb副本集实现

发表于:2026-10-31 作者:千家信息网编辑
千家信息网最后更新 2026年10月31日,MongoDB副本集概述以下图片摘自MongoDB官方文档:http://docs.mongodb.org/manual/core/replication-introduction/Primary节点
千家信息网最后更新 2026年10月31日Mongodb副本集实现

MongoDB副本集概述

以下图片摘自MongoDB官方文档:http://docs.mongodb.org/manual/core/replication-introduction/

Primary节点接收客户端所有的写操作,整个副本集只会有一个primary节点。MongoDB副本集提供严格的一致性。主节点将所有的操作写入一个叫oplog的capped collection(这个collection的大小一般为磁盘剩余空间的5%,不同的系统可能不一样,详见http://docs.mongodb.org/manual/core/replica-set-oplog/)中,secondary节点通过复制oplog并执行oplog中的所有操作,因为对oplog的执行是幂等的,所以secondary节点上的数据可以保持和primary节点一样,当然这有一个"追赶"(catch up)的过程,会存在一定的落后(Lag)有时候因为网络延迟或宕机导致从节点永远赶不上主节点,这时候需要采取人为的干预了(后面会说到Resyncing Member of Replica Set)。

默认所有的读操作也是走的primary节点,当然客户端可以选择从secondary节点进行读取操作以减小主节点的压力(后面会对读写分离有详细说明)。

各个节点之间是通过心跳机制来维持联系的,当主节点无法和集群中其他节点通信超过10秒,集群会从剩下的节点中选择一个secondary作为primary,这个过程叫做选举(election),每个secondary节点都有一个优先级priority来参与投票(也可以有没有投票权的secondary节点),priority值越大就越优先成为主节点(所有的节点可以有相同的优先级,默认值都是1)。election的策略不仅仅就是根据priority值来,会综合很多其他的因素。总之MongoDB通过heartbeat和election机制实现了自动的Failover:

副本集要求参与选举投票(vote)的节点数为奇数,这很容易理解。当我们实际环境中因为机器等原因限制只有两个(或偶数)的节点,这时为了实现Automatic Failover引入另一类节点:仲裁者(arbiter),仲裁者只参与投票不拥有实际的数据,因此它对物理资源要求不严格。

上面已经提到了primary,secondary和arbiter,整个MongoDB副本集群中除了这三种类型的节点还有其他几种:

  • Secondary-Only:这种类型的节点和secondary节点一样拥有数据副本,但是它们在任何情形下都成为不了primary节点。

  • Hidden:这种类型的节点对客户端程序来说是不可见的,同样也不能成为primary节点,但是Hidden成员能够参与选举投票。

  • Delayed:这种类型的成员通过人为的设置,可以指定一个时间来延迟从primary节点同步数据。Delayed成员的作用在于帮助集群从一些误操作中恢复,比如管理员误删除了某个集合。不至于迅速扩散到整个集群中。因此Delayed节点必须不能成为primary节点(priority为0)并且是Hidden的。

  • Non-Voting:这就是上面提到了没有选举权的secondary节点。这种类型的节点一般当集群节点数超过12才会需要。

简单副本集的搭建

主:192.168.1.100

从:192.168.1.101,192.168.1.102

1.首先已经安装完mongodb(我们使用rpm安装)。

mongodb默认端口为:27017

2.修改两个从节点配置文件

service mongod stop vim /etc/mongod.conf

取消注释replSet,设置其名称;并添加replIndexPrefetch项。如下:

重启服务:

service mongod start

3.登录到主节点命令行中

mongo
>rs.status() {    "startupStatus" : 3,    "info" : "run rs.initiate(...) if not yet done for the set","ok" : 0,"errmsg" : "can't get local.system.replset config from self or any seed (YCONFIG)"}

启动一个新的副本集

>rs.initiate()  {"info2" : "no configuration explicitly specified -- making one","me" : "Centos:27017","info" : "Config now saved locally.  Should come online in about a minute"ok" : 1}

在Mongo客户端使用命令rs.initiate()来启动一个新的副本集。

我们可以使用rs.conf()来查看副本集的配置

查看副本集状态使用 rs.status() 命令

副本集添加成员

添加副本集的成员,我们需要使用多条服务器来启动mongo服务。进入Mongo客户端,并使用rs.add()方法来添加副本集的成员。

语法

rs.add() 命令基本语法格式如下:

>rs.add(Host_NAME:PORT)

添加两个从节点成员:

testSet:PRIMARY> rs.add("192.168.1.101") --默认27017不用指定{ "ok" : 1 }testSet:PRIMARY> rs.add("192.168.1.102"){ "ok" : 1 }

此时,查看副本集状态:

testSet:PRIMARY> rs.status(){"set" : "testSet","date" : ISODate("2017-03-22T07:58:26Z"),"myState" : 1,"members" : [{"_id" : 0,"name" : "Centos:27017","health" : 1,"state" : 1,"stateStr" : "PRIMARY","uptime" : 1293,"optime" : Timestamp(1490168420, 1),"optimeDate" : ISODate("2017-03-22T07:40:20Z"),"electionTime" : Timestamp(1490168213, 11),"electionDate" : ISODate("2017-03-22T07:36:53Z"),"self" : true},{"_id" : 1,"name" : "192.168.1.101:27017","health" : 1,"state" : 2,"stateStr" : "SECONDARY","uptime" : 1146,"optime" : Timestamp(1490168420, 1),"optimeDate" : ISODate("2017-03-22T07:40:20Z"),"lastHeartbeat" : ISODate("2017-03-22T07:58:25Z"),"lastHeartbeatRecv" : ISODate("2017-03-22T07:58:25Z"),"pingMs" : 1,"syncingTo" : "Centos:27017"},{"_id" : 2,"name" : "192.168.1.102:27017","health" : 1,"state" : 2,"stateStr" : "SECONDARY","uptime" : 1086,"optime" : Timestamp(1490168420, 1),"optimeDate" : ISODate("2017-03-22T07:40:20Z"),"lastHeartbeat" : ISODate("2017-03-22T07:58:25Z"),"lastHeartbeatRecv" : ISODate("2017-03-22T07:58:24Z"),"pingMs" : 1,"lastHeartbeatMessage" : "syncing to: Centos:27017","syncingTo" : "Centos:27017"}],"ok" : 1}

测试:

在主节点创建新库,并插入新数据:

testSet:PRIMARY> show dbs;admin  (empty)local  6.075GBtestSet:PRIMARY> use testswitched to db testtestSet:PRIMARY> show dbsadmin  (empty)local  6.075GBtestSet:PRIMARY> db.test.insert({"name":"菜鸟教程"})WriteResult({ "nInserted" : 1 })testSet:PRIMARY> show dbsadmin  (empty)local  6.075GBtest   0.078GB

查看从节点信息:

testSet:SECONDARY> show dbs;admin  (empty)local  6.075GBtest   0.078GBtestSet:SECONDARY> db.test.find(){ "_id" : ObjectId("58d231485934aa983f070c99"), "name" : "菜鸟教程" }

问题及解决:
1.初始化副本集时报错:

>rs.initialte(){    ....     "errmsg" "couldn't initiate : can't find self in the replset config" ,"ok" : 0    ....}

解决:编辑hosts文件添加主机名称解析,之后重新初始化副本集。

[root@Centos ~]# vim /etc/hosts127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4::1         localhost localhost.localdomain localhost6 localhost6.localdomain6127.0.0.1 Centos

2.添加副本集成员时报错:

testSet:PRIMARY> rs.add("192.168.1.101:27017"){"errmsg" : "exception: need most members up to reconfigure, not ok : 192.1.101:27017","code" : 13144,"ok" : 0}

解决:由于从节点配置文件中bind绑定为127.0.0.1的ip信息,从而导致不能添加192端的ip,将其bind注释掉。

3.添加完成员,查看副本集状态时,节点一直 显示如:"stateStr" : "UNKNOWN"

解决:问题的原因是rs.initiate()默认将primary的host键设置成机器的主机名,如下:

1)可以编辑两个从节点的hosts文件添加主节点主机名和Ip信息,如:

[root@RedHat-1 ~]# vim /etc/hosts127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4::1         localhost localhost.localdomain localhost6 localhost6.localdomain6192.168.1.100 Centos

2)可以将primary的主机名改成IP地址:

cfg = rs.conf()cfg.members[0].host = "192.168.1.100:27017"rs.reconfig(cfg)


节点 副本 成员 集群 客户 客户端 数据 类型 投票 两个 主机 命令 文件 选举 信息 状态 服务 配置 仲裁者 优先级 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网科技有限公司 深圳恒合互联网络科技有限公司 互联网科技有限公司经营范围 互联网为科技 互联网 科技创新 期待互联网科技 上游互联网科技 互联网科技汛 互联网金融科技委员会 金融科技与互联网金融相同和不同 深圳市优智互联网科技有限公司 工业互联网等科技实现智能化赋能 美国互联网科技实力 云南省自由互联网科技有限公司 四川互联网展示科技馆设计 互联网科技企业商标注意事项 西安左小互联网科技有限公司 互联网科技品牌 宁波允成互联网科技有限公司 前海云享互联网科技 易互联网科技有限公司 杭州互联网科技公司 北京三清互联网科技 互联网科技博主是什么意思 湖北码尼互联网科技有限公司电话 黑科技闪耀互联网之光 为客找房互联网科技公司怎么样 众安科技工业互联网合作 富国互联网科技002692 九思连强互联网电子科技有限公司
0