千家信息网

Mongodb副本集实现

发表于:2025-01-20 作者:千家信息网编辑
千家信息网最后更新 2025年01月20日,MongoDB副本集概述以下图片摘自MongoDB官方文档:http://docs.mongodb.org/manual/core/replication-introduction/Primary节点
千家信息网最后更新 2025年01月20日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安全错误 数据库的锁怎样保障安全 服务器安装虚拟系统报错误代码 音乐网站音乐放在本地还是数据库 女生学软件开发开发 一台服务器能管理的最大存储 一恒优选服务器异常怎么回事 恒深创天网络技术 虹口区网络技术服务产业 wps怎么给人物划分数据库 江西蜗牛互联网科技有限公司 以下是国产数据库的是 自建个人数据库 资产管理后台服务器推荐配置 宁波可易互联网科技 关于防疫网络安全的手抄报 评论区的数据库 广州医院poi数据库 目前数据库的主要管理方法 宁夏浪潮服务器维修维保 区块链的数据库上链 云服务器设备租赁和谁租 数据库怎么保存为sql 河北数据库安全箱定制价格 温州综合服务管理软件开发 卡巴斯基服务器企业版 无锡党委党组网络安全责任 珠海足球软件开发 网络安全工程师什么时候考 剑灵老是与服务器断开连接 运行中无法登录服务器 学软件开发毕业做什么
0