多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
一)理解MongoDB复制集 二)案例 第一个:以三节点为例 操作系统;centos7.3 节点: node1: 10.2.13.187 node2: 10.2.13.186 node3: 10.2.13.185 mongodb版本: Mongodb3.6.3 1)第一步,在所有节点上安装mongodb3.6.3,脚本如下 ~~~ [root@node2 scripts]# cat install_mongodb.sh #!/bin/bash # M_VER=3.6 M_INSTALL_VER=3.6.3 PORT=27017 BIND_IP=$(ifconfig eth0|grep inet|grep -v inet6|awk '{print $2}') function yum_install_mongodb(){ cd /etc/yum.repos.d if [ ! -f mongodb-org-${M_VER}.repo ];then cat >>mongodb-org-${M_VER}.repo <<EOF [mongodb-org-${M_VER}] name = MongoDB Repository baseurl = https://repo.mongodb.org/yum/redhat/7Server/mongodb-org/${M_VER}/x86_64/ gpgcheck = 0 enabled = 1 EOF fi yum install -y mongodb-org-${M_INSTALL_VER} mongodb-org-server-${M_INSTALL_VER} mongodb-org-shell-${M_INSTALL_VER} mongodb-org-mongos-${M_INSTALL_VER} mongodb-org-tools-${M_INSTALL_VER} cd /etc/ && [ ! -f mongod.conf.ori ] && cp /etc/mongod.conf{,.ori} #修改配置文件 sed -i "s@bindIp: 127.0.0.1@bindIp: ${BIND_IP}@g" /etc/mongod.conf #启动mongod服务 systemctl start mongod if [ "`ss -tunl|grep ${PORT}|cut -d: -f2|awk '{print $1}'`" == "${PORT}" ];then echo "mongod start successful" else echo "mongod start fail" fi } main(){ yum_install_mongodb } main ~~~ 2)配置mongod.conf 参数 replication: oplogSizeMB : <int> replSetName : <string> secondaryIndexPrefetch : <string> enableMajorityReadConcern : <boolean> ##在3.6中不推荐使用 replSetResizeOplog使您可以动态调整oplog的大小而不必重新启动mongod进程。 replication.secondaryIndexPrefetch仅适用于mmapv1 存储引擎 * 在node1上操作 replication: oplogSizeMB: 3072 replSetName: repl1 secondaryIndexPrefetch: _id_only 解释: replSet:定义一个复制集的名称,假如三个服务器的mongodb.conf中都需要加入replSet的指定,它们都属于repl1复制集(replSetName) replIndexPrefetch:指定索引预获取行为,[none|_id_only|all] ( secondaryIndexPrefetch) oplogSize:用于复制操作的大小(以MB为单位)日志。默认值是磁盘空间的5% (oplogSizeMB) 启动mongod服务 [root@node1 ~]# systemctl start mongod * 在node2和node3上操作 [root@node3 ~]# vim /etc/mongod.conf replication: oplogSizeMB: 3072 replSetName: repl1 secondaryIndexPrefetch: _id_only 然后重启mongod服务 [root@node3 ~]# systemctl restart mongod 3)配置复制集 在node1上操作 ~~~ [root@node1 ~]# mongo 10.2.13.187:27017 MongoDB shell version v3.6.3 connecting to: mongodb://10.2.13.187:27017/test MongoDB server version: 3.6.3 Server has startup warnings: 2018-03-13T10:29:01.155+0800 I STORAGE [initandlisten] 2018-03-13T10:29:01.155+0800 I STORAGE [initandlisten] ** WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine 2018-03-13T10:29:01.155+0800 I STORAGE [initandlisten] ** See http://dochub.mongodb.org/core/prodnotes-filesystem 2018-03-13T10:29:05.989+0800 I CONTROL [initandlisten] 2018-03-13T10:29:05.989+0800 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database. 2018-03-13T10:29:05.989+0800 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted. 2018-03-13T10:29:05.989+0800 I CONTROL [initandlisten] > rs. rs.add( rs.isMaster( rs.addArb( rs.printReplicationInfo( rs.apply( rs.printSlaveReplicationInfo( rs.bind( rs.propertyIsEnumerable( rs.call( rs.prototype rs.compareOpTimes( rs.reconfig( rs.conf( rs.remove( 当前配置 rs.config( rs.slaveOk( rs.constructor rs.status( rs.debug rs.stepDown( rs.freeze( rs.syncFrom( rs.hasOwnProperty( rs.toLocaleString( rs.help( rs.toString( rs.initiate( rs.valueOf( 初始化 ~~~ * 先初始化并查看状态 ~~~ > rs.initiate() 初始化 { "info2" : "no configuration specified. Using a default configuration for the set", "me" : "10.2.13.187:27017", "ok" : 1, "operationTime" : Timestamp(1520908730, 1), "$clusterTime" : { "clusterTime" : Timestamp(1520908730, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } } } repl1:PRIMARY> rs.status() --查看副本集的状态 { "set" : "repl1", "date" : ISODate("2018-03-13T02:39:47.584Z"), "myState" : 1, "term" : NumberLong(1), "heartbeatIntervalMillis" : NumberLong(2000), "optimes" : { "lastCommittedOpTime" : { "ts" : Timestamp(1520908782, 1), "t" : NumberLong(1) }, "readConcernMajorityOpTime" : { "ts" : Timestamp(1520908782, 1), "t" : NumberLong(1) }, "appliedOpTime" : { "ts" : Timestamp(1520908782, 1), "t" : NumberLong(1) }, "durableOpTime" : { "ts" : Timestamp(1520908782, 1), "t" : NumberLong(1) } }, "members" : [ 显示副本集成员信息 { "_id" : 0, 节点标识 "name" : "10.2.13.187:27017", 节点名称 "health" : 1, 节点健康状态 "state" : 1, 有没有状态信息 "stateStr" : "PRIMARY", 当前节点状态 "uptime" : 646, 运行状态 "optime" : { "ts" : Timestamp(1520908782, 1), "t" : NumberLong(1) }, --oplog中最近一次最后一次oplog操作的时间戳 "optimeDate" : ISODate("2018-03-13T02:39:42Z"), --oplog中最近一次最后一次oplog操作的时间 "infoMessage" : "could not find member to sync from", "electionTime" : Timestamp(1520908730, 2), 选举时间戳 "electionDate" : ISODate("2018-03-13T02:38:50Z"),选举日期 "configVersion" : 1, "self" : true } ], "ok" : 1, "operationTime" : Timestamp(1520908782, 1), "$clusterTime" : { "clusterTime" : Timestamp(1520908782, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } } } ~~~ ~~~ repl1:PRIMARY> rs.add("10.2.13.186:27017") 添加节点 { "ok" : 1, "operationTime" : Timestamp(1520909511, 1), "$clusterTime" : { "clusterTime" : Timestamp(1520909511, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } } } repl1:PRIMARY> rs.status() { "set" : "repl1", "date" : ISODate("2018-03-13T02:51:59.822Z"), "myState" : 1, "term" : NumberLong(1), "heartbeatIntervalMillis" : NumberLong(2000), "optimes" : { "lastCommittedOpTime" : { "ts" : Timestamp(1520909507, 1), "t" : NumberLong(1) }, "appliedOpTime" : { "ts" : Timestamp(1520909511, 1), "t" : NumberLong(1) }, "durableOpTime" : { "ts" : Timestamp(1520909511, 1), "t" : NumberLong(1) } }, "members" : [ { "_id" : 0, "name" : "10.2.13.187:27017", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 1378, "optime" : { "ts" : Timestamp(1520909511, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2018-03-13T02:51:51Z"), "electionTime" : Timestamp(1520908730, 2), "electionDate" : ISODate("2018-03-13T02:38:50Z"), "configVersion" : 2, "self" : true }, { "_id" : 1, "name" : "10.2.13.186:27017", "health" : 1, "state" : 0, "stateStr" : "STARTUP", 追赶主节点的阶段,一旦追赶成功就会显示"SECONDARY",如 "stateStr" : "SECONDARY", "uptime" : 7, "optime" : { "ts" : Timestamp(0, 0), "t" : NumberLong(-1) }, "optimeDurable" : { "ts" : Timestamp(0, 0), "t" : NumberLong(-1) }, "optimeDate" : ISODate("1970-01-01T00:00:00Z"), "optimeDurableDate" : ISODate("1970-01-01T00:00:00Z"), "lastHeartbeat" : ISODate("2018-03-13T02:51:57.837Z"), "lastHeartbeatRecv" : ISODate("1970-01-01T00:00:00Z"), "pingMs" : NumberLong(1), "configVersion" : -2 } ], "ok" : 1, "operationTime" : Timestamp(1520909511, 1), "$clusterTime" : { "clusterTime" : Timestamp(1520909511, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } } } 一旦状态变成"SECONDARY",我们可以登录node2查看 [root@node2 ~]# mongo 10.2.13.186:27017 MongoDB shell version v3.6.3 connecting to: mongodb://10.2.13.186:27017/test MongoDB server version: 3.6.3 Server has startup warnings: 2018-03-13T10:32:03.222+0800 I CONTROL [initandlisten] 2018-03-13T10:32:03.222+0800 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database. 2018-03-13T10:32:03.222+0800 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted. 2018-03-13T10:32:03.222+0800 I CONTROL [initandlisten] 2018-03-13T10:32:03.223+0800 I CONTROL [initandlisten] 2018-03-13T10:32:03.223+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'. 2018-03-13T10:32:03.223+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2018-03-13T10:32:03.223+0800 I CONTROL [initandlisten] 2018-03-13T10:32:03.223+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'. 2018-03-13T10:32:03.223+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2018-03-13T10:32:03.223+0800 I CONTROL [initandlisten] repl1:SECONDARY> ~~~ 错误提示1(在从节点上) ~~~ repl1:SECONDARY> show dbs; 2018-03-13T11:01:43.988+0800 E QUERY [thread1] Error: listDatabases failed:{ "operationTime" : Timestamp(1520910097, 1), "ok" : 0, "errmsg" : "not master and slaveOk=false", "code" : 13435, "codeName" : "NotMasterNoSlaveOk", "$clusterTime" : { "clusterTime" : Timestamp(1520910097, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } } } : _getErrorWithCode@src/mongo/shell/utils.js:25:13 Mongo.prototype.getDBs@src/mongo/shell/mongo.js:65:1 shellHelper.show@src/mongo/shell/utils.js:816:19 shellHelper@src/mongo/shell/utils.js:706:15 @(shellhelp2):1:1 ~~~ 因为从节点默认是不允许读写的,解决这个问题,有两种方式 在从节点上执行rs.slaveOk() 或者在主节点上执行db.getMongo().setSlaveOk() repl1:SECONDARY> rs.slaveOk() repl1:SECONDARY> show dbs admin 0.000GB config 0.000GB local 0.000GB person 0.000GB 在主机节点上操作rs.conf ~~~ rs.conf() { "_id" : "repl1", "version" : 3, "protocolVersion" : NumberLong(1), "members" : [ { "_id" : 0, "host" : "10.2.13.187:27017", "arbiterOnly" : false, 当前节点是不是仲裁节点 "buildIndexes" : true, "hidden" : false,当前节点是否为隐藏节点 "priority" : 1, 当前节点的优先级 "tags" : { }, "slaveDelay" : NumberLong(0), 当前节点是否为延迟复制的 "votes" : 1------是否有选票的资格 }, { "_id" : 1, "host" : "10.2.13.186:27017", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 }, { "_id" : 2, "host" : "10.2.13.185:27017", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 } ], "settings" : { "chainingAllowed" : true, "heartbeatIntervalMillis" : 2000, "heartbeatTimeoutSecs" : 10, "electionTimeoutMillis" : 10000, "catchUpTimeoutMillis" : -1, "catchUpTakeoverDelayMillis" : 30000, "getLastErrorModes" : { }, "getLastErrorDefaults" : { "w" : 1, "wtimeout" : 0 }, "replicaSetId" : ObjectId("5aa739baf02836af4dbcb3c5") } } ~~~ 模拟主节点故障: repl1:PRIMARY> rs.stepDown() repl1:SECONDARY> 此时第三个节点就变成主的 repl1:SECONDARY> repl1:PRIMARY> * 调整属性 1)调整该节点的优先级为2,使其成为主节点(在主节点上操作) repl1:PRIMARY> cfg=rs.conf() repl1:PRIMARY> cfg.members[0].priority=2 repl1:PRIMARY> rs.reconfig(cfg) 然后就发现当前主节点变成 repl1:SECONDARY> 然后优先级为2的节点成为primary节点咯 repl1:PRIMARY> 2)添加仲裁节点 推荐使用 repl1:PRIMARY> rs.addArb("10.2.13.185:27017") 直接添加仲裁节点 把已有的某个节点改成冲裁节点 repl1:PRIMARY> cfg=rs.conf() repl1:PRIMARY> cfg.members[2].arbiterOnly=true true repl1:PRIMARY> rs.reconfig(cfg) 如果没有成功就执行如下操作 ~~~ repl1:PRIMARY> rs.remove("10.2.13.185:27017") { "ok" : 1, "operationTime" : Timestamp(1520913161, 1), "$clusterTime" : { "clusterTime" : Timestamp(1520913161, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } } } repl1:PRIMARY> rs.addArb("10.2.13.185:27017") { "ok" : 1, "operationTime" : Timestamp(1520913184, 1), "$clusterTime" : { "clusterTime" : Timestamp(1520913184, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } } } 使用rs.conf()查看 { "_id" : 2, "host" : "10.2.13.185:27017", "arbiterOnly" : true, "buildIndexes" : true, ~~~ 3)查看各从节点是否落后与主节点多少 repl1:PRIMARY> rs.printSlaveReplicationInfo() source: 10.2.13.186:27017 syncedTo: Tue Mar 13 2018 11:54:23 GMT+0800 (CST) 0 secs (0 hrs) behind the primary source: 10.2.13.185:27017 no replication info, yet. State: (not reachable/healthy) 4) 配置节点成为延迟节点(在主节点上配置) cfg = rs.conf() cfg.members[2].priority = 0 cfg.members[2].hidden = true cfg.members[2].slaveDelay = 3600 rs.reconfig(cfg) * 副本集的维护 1)更改oplog大小 ~~~ repl1:SECONDARY> db.oplog.rs.stats().maxSize NumberLong("3221225472") repl1:SECONDARY> db.adminCommand({replSetResizeOplog:1,size:2048}) { "ok" : 1, "operationTime" : Timestamp(1520915223, 1), "$clusterTime" : { "clusterTime" : Timestamp(1520915223, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } } } repl1:SECONDARY> db.oplog.rs.stats().maxSize NumberLong("2147483648") ~~~ 2)