linux 学习笔记-084-NoSQL-mongodb 副本集介绍,mongodb 副本集搭建和测试

发布于 2018-05-13  203 次阅读


MongoDB 副本集

早期版本使用 master-slave,一主一从和 MySQL 类似,但 slave 在此架构中为只读,当主库宕机后,从库不能自动切换为主

目前已经淘汰 master-slave 模式,改为副本集,这种模式下有一个主(primary),和多个从(secondary),只读。支持给它们设置权重,当主宕掉后,权重最高的从切换为主

在此架构中还可以建立一个仲裁(arbiter)的角色,它只负责裁决,而不存储数据

再此架构中读写数据都是在主上,要想实现负载均衡的目的需要手动指定读库的目标 server

副本集架构图

linux 学习笔记-084-NoSQL-mongodb 副本集介绍,mongodb 副本集搭建和测试

linux 学习笔记-084-NoSQL-mongodb 副本集介绍,mongodb 副本集搭建和测试

mongodb 副本集搭建

需准备三台机器,172.17.1.240(primary),172.17.1.242(secondary),172.17.1.243(secondary),三台机器均安装 mongodb

242 和 243 安装 mongodb

[root@am-02:~#] vim /etc/yum.repos.d/mongodb.repo

[mongodb-org-3.6]

name=MongoDB Repository

baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.6/x86_64/

gpgcheck=1

enabled=1

gpgkey=https://www.mongodb.org/static/pgp/server-3.6.asc

[root@am-02:~#] yum -y install mongodb-org
[root@am-03:~#] vim /etc/yum.repos.d/mongodb.repo

[mongodb-org-3.6]

name=MongoDB Repository

baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.6/x86_64/

gpgcheck=1

enabled=1

gpgkey=https://www.mongodb.org/static/pgp/server-3.6.asc

[root@am-03:~#] yum -y install mongodb-org

修改三台机器的配置文件

[root@am-01:~#] vim /etc/mongod.conf

bindIp: 127.0.0.1,172.17.1.24

#需监听本机内网 IP

replication:

  oplogSizeMB: 20

#定义 oplog 大小

  replSetName: am

#定义复制集名称

[root@am-01:~#] systemctl restart mongod.service

[root@am-01:~#] netstat -lntp | grep mon

tcp        0      0 172.17.1.240:27017      0.0.0.0:*               LISTEN      75601/mongod       

tcp        0      0 127.0.0.1:27017         0.0.0.0:*               LISTEN      75601/mongod     
[root@am-02:~#] vim /etc/mongod.conf

bindIp: 127.0.0.1,172.17.1.242

replication:

  oplogSizeMB: 20

  replSetName: am

[root@am-02:~#] systemctl restart mongod.service

[root@am-02:~#] netstat -lntp | grep mon

tcp        0      0 172.17.1.242:27017      0.0.0.0:*               LISTEN      4939/mongod        

tcp        0      0 127.0.0.1:27017         0.0.0.0:*               LISTEN      4939/mongod   
[root@am-03:~#] vim /etc/mongod.conf

bindIp: 127.0.0.1,172.17.1.243

replication:

  oplogSizeMB: 20

  replSetName: am

[root@am-03:~#] systemctl restart mongod.service

[root@am-03:~#] netstat -lntp | grep mon

tcp        0      0 172.17.1.243:27017      0.0.0.0:*               LISTEN      5075/mongod        

tcp        0      0 127.0.0.1:27017         0.0.0.0:*               LISTEN      5075/mongod  

设置适当的 iptables 规则(我这里清空规则),关闭 SElinux

[root@am-01:~#] iptables -nvL

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)

 pkts bytes target     prot opt in     out     source               destination        



Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)

 pkts bytes target     prot opt in     out     source               destination        



Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)

 pkts bytes target     prot opt in     out     source               destination        

[root@am-01:~#] getenforce

Disabled
[root@am-02:~#] iptables -nvL

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)

 pkts bytes target     prot opt in     out     source               destination        



Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)

 pkts bytes target     prot opt in     out     source               destination        



Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)

 pkts bytes target     prot opt in     out     source               destination        

[root@am-02:~#] getenforce

Disabled
[root@am-03:~#] iptables -nvL

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)

 pkts bytes target     prot opt in     out     source               destination         



Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)

 pkts bytes target     prot opt in     out     source               destination        



Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)

 pkts bytes target     prot opt in     out     source               destination        

[root@am-03:~#] getenforce

Disabled

连接主,在主上运行命令

[root@am-01:~#] mongo

> config={_id:"am",members:[{_id:0,host:"172.17.1.240:27017"},{_id:1,host:"172.17.1.242:27017"},{_id:2,host:"172.17.1.243:27017"}]}

{

       "_id" : "am",

       "members" : [

              {

                     "_id" : 0,

                     "host" : "172.17.1.240:27017"

              },

              {

                     "_id" : 1,

                     "host" : "172.17.1.242:27017"

              },

              {

                     "_id" : 2,

                     "host" : "172.17.1.243:27017"

              }

       ]

}

#配置副本集

> rs.initiate(config)

{

       "ok" : 1,

       "operationTime" : Timestamp(1526056824, 1),

       "$clusterTime" : {

              "clusterTime" : Timestamp(1526056824, 1),

              "signature" : {

                     "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),

                     "keyId" : NumberLong(0)

              }

       }

}

#初始化,有"ok 1"字眼则成功了

am:OTHER> rs.status()

{

       "set" : "am",

       "date" : ISODate("2018-05-11T16:42:18.935Z"),

       "myState" : 1,

       "term" : NumberLong(1),

       "heartbeatIntervalMillis" : NumberLong(2000),

       "optimes" : {

              "lastCommittedOpTime" : {

                     "ts" : Timestamp(1526056937, 1),

                     "t" : NumberLong(1)

              },

              "readConcernMajorityOpTime" : {

                     "ts" : Timestamp(1526056937, 1),

                     "t" : NumberLong(1)

              },

              "appliedOpTime" : {

                     "ts" : Timestamp(1526056937, 1),

                     "t" : NumberLong(1)

              },

              "durableOpTime" : {

                     "ts" : Timestamp(1526056937, 1),

                     "t" : NumberLong(1)

              }

       },

       "members" : [

              {

                     "_id" : 0,

                     "name" : "172.17.1.240:27017",

                     "health" : 1,

                     "state" : 1,

                     "stateStr" : "PRIMARY",

                     "uptime" : 740,

                     "optime" : {

                            "ts" : Timestamp(1526056937, 1),

                            "t" : NumberLong(1)

                     },

                     "optimeDate" : ISODate("2018-05-11T16:42:17Z"),

                     "infoMessage" : "could not find member to sync from",

                     "electionTime" : Timestamp(1526056835, 1),

                     "electionDate" : ISODate("2018-05-11T16:40:35Z"),

                     "configVersion" : 1,

                     "self" : true

              },

              {

                     "_id" : 1,

                     "name" : "172.17.1.242:27017",

                     "health" : 1,

                     "state" : 2,

                     "stateStr" : "SECONDARY",

                     "uptime" : 114,

                     "optime" : {

                            "ts" : Timestamp(1526056937, 1),

                            "t" : NumberLong(1)

                     },

                     "optimeDurable" : {

                            "ts" : Timestamp(1526056937, 1),

                            "t" : NumberLong(1)

                     },

                     "optimeDate" : ISODate("2018-05-11T16:42:17Z"),

                     "optimeDurableDate" : ISODate("2018-05-11T16:42:17Z"),

                     "lastHeartbeat" : ISODate("2018-05-11T16:42:17.582Z"),

                     "lastHeartbeatRecv" : ISODate("2018-05-11T16:42:18.260Z"),

                     "pingMs" : NumberLong(0),

                     "syncingTo" : "172.17.1.240:27017",

                     "configVersion" : 1

              },

              {

                     "_id" : 2,

                     "name" : "172.17.1.243:27017",

                     "health" : 1,

                     "state" : 2,

                     "stateStr" : "SECONDARY",

                     "uptime" : 114,

                     "optime" : {

                            "ts" : Timestamp(1526056937, 1),

                            "t" : NumberLong(1)

                     },

                     "optimeDurable" : {

                            "ts" : Timestamp(1526056937, 1),

                            "t" : NumberLong(1)

                     },

                     "optimeDate" : ISODate("2018-05-11T16:42:17Z"),

                     "optimeDurableDate" : ISODate("2018-05-11T16:42:17Z"),

                     "lastHeartbeat" : ISODate("2018-05-11T16:42:17.582Z"),

                     "lastHeartbeatRecv" : ISODate("2018-05-11T16:42:18.097Z"),

                     "pingMs" : NumberLong(0),

                     "syncingTo" : "172.17.1.240:27017",

                     "configVersion" : 1

              }

       ],

       "ok" : 1,

       "operationTime" : Timestamp(1526056937, 1),

       "$clusterTime" : {

              "clusterTime" : Timestamp(1526056937, 1),

              "signature" : {

                     "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),

                     "keyId" : NumberLong(0)

              }

       }

}

#查看副本集状态

#如果两个从上的状态为"stateStr" : "STARTUP", 则需要进行如下操作

> var config={_id:"am",members:[{_id:0,host:"172.17.1.240:27017"},{_id:1,host:"172.17.1.242:27017"},{_id:2,host:"172.17.1.243:27017"}]}

> rs.reconfig(config)

此时再次查看 rs.status()会发现从的状态变为 SECONDARY

#如果想哪一台机器作为 PRIMARY,就在哪一台机器上做以上配置副本集的操作

mongodb 副本集测试

在主上建库,建集合

[root@am-01:~#] mongo

am:PRIMARY> use mydb

switched to db mydb

am:PRIMARY> db.acc.insert({AccountID:1,UserName:"123",password:"123456"})

WriteResult({ "nInserted" : 1 })

am:PRIMARY> show dbs

admin   0.000GB

config  0.000GB

db1     0.000GB

local   0.000GB

mydb    0.000GB

test    0.000GB

在从上测试

[root@am-02:~#] mongo

am:SECONDARY> show dbs

2018-05-12T00:53:30.568+0800 E QUERY    [thread1] Error: listDatabases failed:{

       "operationTime" : Timestamp(1526057607, 1),

       "ok" : 0,

       "errmsg" : "not master and slaveOk=false",

       "code" : 13435,

       "codeName" : "NotMasterNoSlaveOk",

       "$clusterTime" : {

              "clusterTime" : Timestamp(1526057607, 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:820:19

shellHelper@src/mongo/shell/utils.js:710:15

@(shellhelp2):1:1

#提示错误

am:SECONDARY> rs.slaveOk()

am:SECONDARY> show dbs

admin   0.000GB

config  0.000GB

db1     0.000GB

local   0.000GB

mydb    0.000GB

test    0.000GB

am:SECONDARY> use mydb

switched to db mydb

am:SECONDARY> show tables

acc

#执行"rs.slaveOk()",再"show dbs"
[root@am-03:~#] mongo

am:SECONDARY> rs.slaveOk()

am:SECONDARY> show dbs

admin   0.000GB

config  0.000GB

db1     0.000GB

local   0.000GB

mydb    0.000GB

test    0.000GB

am:SECONDARY> use mydb

switched to db mydb

am:SECONDARY> show tables

acc

副本集更改权重模拟主宕机

默认三台机器权重都为 1,如果任何一个权重设置为比其他的高,则该台机器马上切换为 primary 角色,所以我们预设三台机器的权重分别为:140 -- 3,142 -- 2,143 -- 1

查看权重(priority)

am:PRIMARY> rs.config()

{

       "_id" : "am",

       "version" : 1,

       "protocolVersion" : NumberLong(1),

       "members" : [

              {

                     "_id" : 0,

                     "host" : "172.17.1.240:27017",

                     "arbiterOnly" : false,

                     "buildIndexes" : true,

                     "hidden" : false,

                     "priority" : 1,

                     "tags" : {

                           

                     },

                     "slaveDelay" : NumberLong(0),

                     "votes" : 1

              },

              {

                     "_id" : 1,

                     "host" : "172.17.1.242:27017",

                     "arbiterOnly" : false,

                     "buildIndexes" : true,

                     "hidden" : false,

                     "priority" : 1,

                     "tags" : {

                           

                     },

                     "slaveDelay" : NumberLong(0),

                     "votes" : 1

              },

              {

                     "_id" : 2,

                     "host" : "172.17.1.243: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("5af5c7773b61d52cd0d6d24f")

       }

}

设置各机器权重

am:PRIMARY> rs.config()

am:PRIMARY> cfg.members[0].priority = 3

3

am:PRIMARY> cfg.members[1].priority = 2

2

am:PRIMARY> cfg.members[2].priority = 1

1

am:PRIMARY> rs.reconfig(cfg)

{

       "ok" : 1,

       "operationTime" : Timestamp(1526058465, 1),

       "$clusterTime" : {

              "clusterTime" : Timestamp(1526058465, 1),

              "signature" : {

                     "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),

                     "keyId" : NumberLong(0)

              }

       }

}

把主的 27017 端口封闭,模拟宕机

[root@am-01:~#] iptables -I INPUT -p tcp --dport 27017 -j DROP

[root@am-01:~#] mongo

MongoDB shell version v3.6.4

connecting to: mongodb://127.0.0.1:27017

2018-05-12T01:09:53.760+0800 W NETWORK  [thread1] Failed to connect to 127.0.0.1:27017 after 5000ms milliseconds, giving up.

2018-05-12T01:09:53.761+0800 E QUERY    [thread1] Error: couldn't connect to server 127.0.0.1:27017, connection attempt failed :

connect@src/mongo/shell/mongo.js:251:13

@(connect):1:6

exception: connect failed

#这时,原来的主已经不能连接 mongodb 了

在权重为 2 的 242 上查看

[root@am-02:~#] mongo

am:PRIMARY> rs.status()

       "members" : [

              {

                     "_id" : 1,

                     "name" : "172.17.1.242:27017",

                     "health" : 1,

                     "state" : 1,

                     "stateStr" : "PRIMARY",

                     "uptime" : 2627,

                     "optime" : {

                            "ts" : Timestamp(1526058930, 1),

                            "t" : NumberLong(26)

                     },

#可以见到 242 已经变成主了