ITPub博客

首页 > 数据库 > NoSQL > MongoDB Replica Set

MongoDB Replica Set

原创 NoSQL 作者:三年二班 时间:2021-05-07 22:51:54 0 删除 编辑

                                                                                                                                                                                          mybk_yzy  

  当下数据为王的时代,数据的重要性已经和土地,劳动力,资本一样不分伯仲。尤其近年来各色各样的数据级公司相对崛起,数据的安全已经成为了决一兴败的关键。数据库的选型亦然成为了热度比较高的话题讨论。产品的存在必然有它存在的意义,产品的诞生的目地往往是为了弥补市场的空白,但也存在着另一个层次的目的,替代那些原有老旧维护力度不高的产品。

 

     MongoDB 介于关系数据库和非关系数据库之间,相对于Mysql在表结构的扩展性方面非常松散灵活,此外,在海量数据存储,读写分离及弹性扩展的层面上也是相对弥补了Mysql集中式架构带来的弊端。在事务层次方面略逊于传统关系型数据库, MongoDB 4.0 引入的事务功能,支持多文档ACID特性 。这对要求数据一致性较强的业务场景也多了一份选择。反过来思考,当下数据库产品各具千秋, 没有任何一种数据库能100%适用于任何业务场景,不断的尝试创新,融合才是保证数据高效的初心。

 

      对于MongoDB,可以支持使用单节点模式提供服务,但是在实际的生产环境中,单机模式将面临很大的风险,一旦这个数据库服务出现问题,就会导致线上的服务出现错误甚至崩溃。因此,在实际生产环境下,需要对MongoDB做相应的主备处理,提高数据库服务的可用性。复本集(Replica Set)的方式做主备处理是目前官方社区推荐的高可用方案。

 

描述服务器环境Centos7的操作系统,Mongo3.4.2安装介质,节点分布情况大致为:

Host

Ip

softWare

Port

Usage

note

OS

node-1

192.168.56.103

mongo 3.4

28001

Primary

主节点

CentOS 7.6

node-2

192.168.56.101

mongo 3.4

28001

Secondary

从节点

CentOS 7.6

node-3

192.168.56.102

mongo 3.4

28001

Arbiter

仲裁节点

CentOS 7.6

要实现的业务目地 : 使用Replica Sets来实现读写分离, Secondary负责读的操作,Primary负责写的操作。减轻数据库压力。

 

                      

 

复制原理:

     如网上这张图所展示的执行顺序,Primary节点写入数据,Secondary通过读取Primary的oplog得到复制信息,开始复制数据并且将复制信息写入到自己的oplog。如果某个操作失败,则备份节点停止从当前数据源复制数据。如果某个备份节点由于某些原因挂掉了,当重新启动后,就会自动从oplog的最后一个操作开始同步,同步完成后,将信息写入自己的oplog,由于复制操作是先复制数据,复制完成后再写入oplog,有可能相同的操作会同步两份,不过MongoDB在设计之初就考虑到这个问题,由于oplog属于高幂等性,将oplog的同一个操作执行多次,与执行一次的效果是一样的。做MySql的都知道PTR,利用的就是全备+binlog恢复,MongoDB在这一点上跟mysql是一样的。

当Primary节点完成数据操作后,Secondary会做出一系列的动作保证数据的同步:

1.检查自己local库的oplog.rs集合找出最近的时间戳。

2.检查Primary节点local库oplog.rs集合,找出大于此时间戳的记录。

3.将找到的记录插入到自己的oplog.rs集合中,并执行这些操作。

副本集的同步和主从同步一样,都是异步同步的过程,不同的是副本集有个自动故障转移的功能。其原理是slave端从primary端获取日志,然后在自己身上完全顺序的执行日志所记录的各种操作(该日志是不记录查询操作的),这个日志就是local数据 库中的oplog.rs表,默认在64位机器上这个表是比较大的,占磁盘大小的5%,oplog.rs的大小可以在启动参数中设 定:--oplogSize 1000,单位是M。

注意,在副本集的环境中,要是所有的Secondary都宕机了,只剩下Primary。最后Primary会变成Secondary,不能提供服务。

部署副本集操作流程:

3台服务器全部安装mongoDB,提前规划好各个节点的分布。我是编写shell 进行自动化安装。

安装流程相对简单,本篇笔记不多做介绍。

pwd

/home/mogodb3/mongod.conf

配置文件 mongod.conf  如下:

port=28001 #实例端口

dbpath=/data/whale28001_mongo3/data#数据存储路径

logpath=/data/whale28001_mongo3/log/mongodb3.log#日志存取路径

pidfilepath=/data/whale28001_mongo3/primary.pid#服务实例ID

directoryperdb=true# 数据目录存储模式,每个数据库的文件存储在DBPATH指定目录的不同的文件夹中。使用此选项,可以配置的MongoDB将数据存储在不同的磁盘设备上,以提高写入吞吐量或磁盘容量。默认为false。

logappend=true#日志追加

fork=true#后台进程运行实例

maxConns=500#最大连接数,根据系统环境调整

auth=false#关闭权限校验

journal=false#数据故障恢复和持久化数据

storageEngine=wiredTiger#数据引擎

bind_ip =0.0.0.0

quiet=false#日志是否记录事件关闭和连接日志信息

oplogSize=100#日志大小,这个设置挺有意思的,太大浪费性能,太小不满足,(请指点)

noprealloc=true#磁盘预分配空间,防止数据增量过快防止IO阻塞

replSet=monitor#副本集名称

启动各个节点mongo服务:

pwd

/home/mogodb3/bin

启动mongo:

./mongod --config /home/mogodb3/mongod.conf

建立mongo 连接:

 ./mongo 192.168.56.103:28001

注意,刚建立的mongoDB 数据库服务,需要在mongod.conf 中 将auth权限认证关闭auth=false。再去创建数据库和对应账户。另外,关闭权限认证,登录用户会看见系统库,不安全。如若对外方提供账号不建议。

1.use admin;#选择库

2.创建 admin 库的所属用户admin 角色为数据库管理角色。如果在副本集运行过程中创建节点数据库对应的角色提示 not master相关关键字,则说明的是该节点目前不可添加,需要把集群关系中断关闭其他节点再次尝试创建用户。

 

在mongoShell中创建用户:db.createUser({user:"admin", pwd:"admin", roles:[{role:"userAdminAnyDatabase", db:"admin"}]})

#查看当前数据库的所有用户

show users();

MongoShell  创建数据库的注意点 使用use 创建数据库 use mydb; 然后show dbs; 你会发现新建的数据库不显示。因为show dbs  不会显示空的数据库。需要插入一条记录才可显示数据库。 db.mydb.insert("date":"20210506");

  后再次查看可看到新库。   db.mongo.find(); 查看插入记录。

                          

接下来的操作给刚刚创建的mydb数据库创建用户,并赋予角色权限和指定数据库。

db.createUser(

 {

   user: "mydb",

   pwd: "mydb",

   roles: [ { role: "dbOwner", db: "mydb" } ]

 }

)

再次给用户增加用户 readWrite 角色权限。

db.grantRolesToUser("mydb", [ { role: "readWrite", db: "mydb" } ])

查看赋值后的用户属性。

 

各个节点创建完用户后在各个节点启动MongoServer,开始配置高可用副本集,明确节点分布,定制集群配置,priority设置的等级越高越容易成为主节点。_id 后为集群名称。

cfg={

_id:"monitor",

members:[{_id:0,host:'192.168.56.103:28001',priority:2},{_id:1,host:'192.168.56.101:28001',priority:1},{_id:2,host:'192.168.56.102:28001',arbiterOnly:true}]

};

rs.initiate(cfg);   //初始化配置

rs.reconfig( cfg );   //使配置生效

rs.reconfig( cfg , { force: true})//强制使其配置文件生效,生效后MongoShell光标会发生变化

主节点查看集群状态:

monitor:PRIMARY> rs.status()

{

"set" : "monitor",#集群名称

"date" : ISODate("2021-05-04T08:00:43.742Z"),

"myState" : 1,#状态

"term" : NumberLong(11),

"heartbeatIntervalMillis" : NumberLong(2000),

"optimes" : {

"lastCommittedOpTime" : {

"ts" : Timestamp(0, 0),

"t" : NumberLong(-1)

},

"appliedOpTime" : {

"ts" : Timestamp(1620115242, 1),

"t" : NumberLong(11)

},

"durableOpTime" : {

"ts" : Timestamp(1620112370, 1),

"t" : NumberLong(10)

}

},

"members" : [

{

"_id" : 0,

"name" : "192.168.56.103:28001",

"health" : 1,

"state" : 1,

"stateStr" : "PRIMARY",#主节点

"uptime" : 2663,

"optime" : {

"ts" : Timestamp(1620115242, 1),

"t" : NumberLong(11)

},

"optimeDate" : ISODate("2021-05-04T08:00:42Z"),

"electionTime" : Timestamp(1620112591, 1),

"electionDate" : ISODate("2021-05-04T07:16:31Z"),

"configVersion" : 4,

"self" : true

},

{

"_id" : 1,

"name" : "192.168.56.101:28001",

"health" : 1,

"state" : 2,

"stateStr" : "SECONDARY",#复制节点

"uptime" : 2662,

"optime" : {

"ts" : Timestamp(1620115232, 1),

"t" : NumberLong(11)

},

"optimeDurable" : {

"ts" : Timestamp(1620112370, 1),

"t" : NumberLong(10)

},

"optimeDate" : ISODate("2021-05-04T08:00:32Z"),

"optimeDurableDate" : ISODate("2021-05-04T07:12:50Z"),

"lastHeartbeat" : ISODate("2021-05-04T08:00:41.876Z"),

"lastHeartbeatRecv" : ISODate("2021-05-04T08:00:42.146Z"),

"pingMs" : NumberLong(0),

"syncingTo" : "192.168.56.103:28001",

"configVersion" : 4

},

{

"_id" : 2,

"name" : "192.168.56.102:28001",

"health" : 1,

"state" : 7,

"stateStr" : "ARBITER",#仲裁节点

"uptime" : 2662,

"lastHeartbeat" : ISODate("2021-05-04T08:00:41.876Z"),

"lastHeartbeatRecv" : ISODate("2021-05-04T08:00:39.498Z"),

"pingMs" : NumberLong(0),

"configVersion" : 4

}

],

"ok" : 1

}

查看副本集信息:

monitor:PRIMARY> db.isMaster()

{

"hosts" : [

"192.168.56.103:28001",#主节点

"192.168.56.101:28001"#备份节点

],

"arbiters" : [

"192.168.56.102:28001"#仲裁节点

],

"setName" : "monitor",#集群名称

"setVersion" : 4,

"ismaster" : true,

"secondary" : false,

"primary" : "192.168.56.103:28001",

"me" : "192.168.56.103:28001",

"electionId" : ObjectId("7fffffff000000000000000b"),

"lastWrite" : {

"opTime" : {

"ts" : Timestamp(1620199579, 1),

"t" : NumberLong(11)

},

"lastWriteDate" : ISODate("2021-05-05T07:26:19Z")

},

"maxBsonObjectSize" : 16777216,

"maxMessageSizeBytes" : 48000000,

"maxWriteBatchSize" : 1000,

"localTime" : ISODate("2021-05-05T07:26:22.197Z"),

"maxWireVersion" : 5,

"minWireVersion" : 0,

"readOnly" : false,

"ok" : 1

}

 

登录不同的节点进行mongo连接,会进入不同的mongoShell 界面,使用可视化工具连接主节点和复制节点,模式选Replica Set连接,俩个节点都有mydb这个库,并有着对应的数据库用户,mongo的用户是指定库的,连接后 在主节点PRIMARY端创建个新表并插入测试数据。

 

刷新从节点服务端表数据,发现已经从主节点同步过来了刚刚新增过来的数据记录。为了更好的测试数据同步机制。在主节点上导入一个备数据,测试节点是否也会有同样的表。主节点恢复数据操作:

备份数据:

/home/mongodb3/mongodump --host 127.0.0.1 --port 28001 -u admin -p admin

  --authenticationDatabase admin -d newdb   -c wb0097xxxry_all  -o /data/bak

恢复备份数据:

/home/mogodb3/bin/mongorestore --host 127.0.0.1 --port 28001 -u admin -p admin  --authenticationDatabase admin -d mydb  /data/bak

恢复完成后发现各个复制节点已经有这张表说明副本集可用,数据同步机制正在生效。

 

副本集添加新备份节点:

  在主节点添加节点: rs.add("192.168.104:28001");返回1说明添加节点生效。

 

查看副本集状态,发现节点状态异常为not healthy。

 

最有效的解决方法,先关闭新节点数据库,一定不要使用kill -9 pid 的方式停止服务。 ./mongod --shutdown -f /home/ mongodb3/mogod.conf

再清空新节点下 数据目录的文件数据 重新启动。rm -rf  *

./mongod --config /home/mongodb3/mongod.conf --replSet monitor

在主节点查看集群状态,发现新添加节点状态还是不健康,解决办法删除该节点重新添加。

rs.remove("192.168.56.104:28001")

rs.add("192.168.56.104:28001");

rs.status();集群状态恢复正常。

 

本篇笔记偏基础的介绍了MongoDB高可用的实践来保证业务的稳定和数据库的健壮性。还有很多工作中经常用到的点在这里没介绍到,接下来会力争在空闲时间内使用python 达到集群的自动化配置和高容灾策略的实现。人算不如天算,做数据行业的多考虑一点风险还是好的。希望各位老师多点评,不吝指教。


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69999437/viewspace-2770831/ ,如需转载,请注明出处,否则将追究法律责任。

上一篇: 没有了~
请登录后发表评论 登录
全部评论
工作在沈阳毕业俩年多的数据治理行业的毛头小子。写博客的目的就是为了积累进步,请各位不吝指教。

注册时间:2021-05-05

  • 博文量
    2
  • 访问量
    949