Replica Set是mongod的实例集合,它们有着同样的数据内容。包含三类角色:
[1]主节点(Primary)
接收所有的写请求,然后把修改同步到所有Secondary。一个Replica Set只能有一个Primary节点,当Primary挂掉后,其他Secondary或者Arbiter节点会重新选举出来一个主节点。默认读请求也是发到Primary节点处理的,需要转发到Secondary需要客户端修改一下连接配置。
[2]副本节点(Secondary)
与主节点保持同样的数据集。当主节点挂掉的时候,参与选主。
[3]仲裁者(Arbiter)
不保有数据,不参与选主,只进行选主投票。使用Arbiter可以减轻数据存储的硬件需求,Arbiter跑起来几乎没什么大的硬件资源需求,但重要的一点是,在生产环境下它和其他数据节点不要部署在同一台机器上。
注意,一个自动failover的Replica Set节点数必须为奇数,目的是选主投票的时候要有一个大多数才能进行选主决策。
[4]选主过程
其中Secondary宕机,不受影响,若Primary宕机,会进行重新选主
安装部署
部署安装3个mongodb实例;分别为master服务器Primary,和slave1服务器(备份服务器副本secondary),从slave2服务器(仲裁服务器arbiter)
[1].配置master
mkdir -p /app/mongodb/cluster/master_mongodb/{log,db,install}
wget -P /app/mongodb/cluster/master_mongodb/install/ https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.2.16.tgz
cd /app/mongodb/cluster/master_mongodb/install/ && tar -xvzf mongodb-linux-x86_64-3.2.16.tgz && rm -rf mongodb-linux-x86_64-3.2.16.tgz
mv mongodb-linux-x86_64-3.2.16 ../mongodb && cd /app/mongodb/cluster/
cat > /app/mongodb/cluster/master_mongodb/mongodb/mongodb.conf << EOF
dbpath=/app/mongodb/cluster/master_mongodb/db
logpath=/app/mongodb/cluster/master_mongodb/log/mongodb.log
port=27017
fork=true
nohttpinterface=true
bind_ip = 0.0.0.0
replSet=Mgo_mt/127.0.0.1:27018
EOF
2.配置slave1(备份)
cp -a /app/mongodb/cluster/master_mongodb /app/mongodb/cluster/slave_mongodb1
cat > /app/mongodb/cluster/slave_mongodb1/mongodb/mongodb.conf<< EOF
dbpath=/app/mongodb/cluster/slave_mongodb1/db
logpath=/app/mongodb/cluster/slave_mongodb1/log/mongodb.log
port=27018
fork=true
nohttpinterface=true
bind_ip = 0.0.0.0
replSet=Mgo_mt/127.0.0.1:27017
EOF
3.配置slave2(仲裁)
cp -a /app/mongodb/cluster/master_mongodb /app/mongodb/cluster/slave_mongodb2
cat >/app/mongodb/cluster/slave_mongodb2/mongodb/mongodb.conf<< EOF
dbpath=/app/mongodb/cluster/slave_mongodb2/db
logpath=/app/mongodb/cluster/slave_mongodb2/log/mongodb.log
port=27019
fork=true
nohttpinterface=true
bind_ip = 0.0.0.0
replSet=Mgo_mt/127.0.0.1:27017
EOF
接下来启动指定主从即可。
4.开启master,slave1,slave2服务器
/app/mongodb/cluster/master_mongodb/mongodb/bin/mongod -f /app/mongodb/cluster/master_mongodb/mongodb/mongodb.conf
/app/mongodb/cluster/slave_mongodb1/mongodb/bin/mongod -f /app/mongodb/cluster/slave_mongodb1/mongodb/mongodb.conf
/app/mongodb/cluster/slave_mongodb2/mongodb/bin/mongod -f /app/mongodb/cluster/slave_mongodb2/mongodb/mongodb.conf
5.登录master配置副本集
登录master执行如下命令:
/app/mongodb/cluster/master_mongodb/mongodb/bin/mongo 127.0.0.1:27017/admin
#添加从服务器和仲裁服务器;配置仲裁服务器:利用哨兵检查集群状态和仲裁投票。注意:哨兵不参与数据的同步,只参与投票和状态检查。
db.runCommand({"replSetInitiate":{ "_id":"Mgo_mt", "members":[ {"_id":1,"host":"127.0.0.1:27017"},{"_id":2,"host":"127.0.0.1:27018"}]}}) #添加从27018
rs.addArb("127.0.0.1:27019") #添加仲裁27019
6.查看状态:
Mgo_mt:PRIMARY> rs.status()
{
"set" : "Mgo_mt",
"date" : ISODate("2019-03-28T09:57:43.689Z"),
"myState" : 1,
"term" : NumberLong(1),
"heartbeatIntervalMillis" : NumberLong(2000),
"members" : [
{
"_id" : 1,
"name" : "127.0.0.1:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 2379,
"optime" : {
"ts" : Timestamp(1553766986, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2019-03-28T09:56:26Z"),
"electionTime" : Timestamp(1553766519, 1),
"electionDate" : ISODate("2019-03-28T09:48:39Z"),
"configVersion" : 2,
"self" : true
},
{
"_id" : 2,
"name" : "127.0.0.1:27018",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 555,
"optime" : {
"ts" : Timestamp(1553766986, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2019-03-28T09:56:26Z"),
"lastHeartbeat" : ISODate("2019-03-28T09:57:42.849Z"),
"lastHeartbeatRecv" : ISODate("2019-03-28T09:57:42.862Z"),
"pingMs" : NumberLong(0),
"syncingTo" : "127.0.0.1:27017",
"configVersion" : 2
},
{
"_id" : 3,
"name" : "127.0.0.1:27019",
"health" : 1,
"state" : 7,
"stateStr" : "ARBITER",
"uptime" : 76,
"lastHeartbeat" : ISODate("2019-03-28T09:57:42.850Z"),
"lastHeartbeatRecv" : ISODate("2019-03-28T09:57:41.892Z"),
"pingMs" : NumberLong(0),
"configVersion" : 2
}
],
"ok" : 1
}
7.查看
#stateStr:PRIMARY--27017,27017位
"stateStr" : "SECONDARY", 27018为从
"stateStr" : "ARBITER",27019为仲裁
8.登录从检查状态:
/app/mongodb/cluster/slave_mongodb1/mongodb/bin/mongo 127.0.0.1:27018
/app/mongodb/cluster/slave_mongodb2/mongodb/bin/mongo 127.0.0.1:27019
查看状态:
rs.status()是否与master一致。
9.测试1:master创建wyl测试库并插入数据。查看slave从库1和slave2哨兵
在master上面执行:
Mgo_mt:PRIMARY> use wyl;
switched to db wyl
Mgo_mt:PRIMARY> db.wyl_test.insert({"name":"wyl","age":"10"})
WriteResult({ "nInserted" : 1 })
Mgo_mt:PRIMARY> db.wyl_test.find()
{ "_id" : ObjectId("5c9c9dfdbca21d51a5bf78ac"), "name" : "wyl", "age" : "10" }
登录slave1查看:注意默认从库没有读操作:需要执行s.slaveOk()
Mgo_mt:SECONDARY> show dbs;
local 0.000GB
wyl 0.000GB
Mgo_mt:SECONDARY> rs.slaveOk()
Mgo_mt:SECONDARY> show dbs;
local 0.000GB
wyl 0.000GB
Mgo_mt:SECONDARY> use wyl;
switched to db wyl
Mgo_mt:SECONDARY> db.wyl_test.find()
{ "_id" : ObjectId("5c9c9dfdbca21d51a5bf78ac"), "name" : "wyl", "age" : "10" }
登录slave2哨兵查看:
Mgo_mt:ARBITER> rs.slaveOk()
Mgo_mt:ARBITER> show dbs;
local 0.000GB
#哨兵不参与数据的同步。所以并没有wyl数据库。
10.测试2:关闭master查看是否会切换
kill -2 57814 #kill掉master 进程
登录从1查看状态:
Mgo_mt:PRIMARY> rs.status()
可以看出:
"stateStr" : "(not reachable/healthy)"--27017已经不可达
"stateStr" : "PRIMARY",27018为主master [之前的从变成了主]
"stateStr" : "ARBITER",27019为仲裁不变
11.测试3:重新开启之前停掉的master
/app/mongodb/cluster/master_mongodb/mongodb/bin/mongod -f /app/mongodb/cluster/master_mongodb/mongodb/mongodb.conf
rs.status()#查看状态此时:
之前的主已经变成了从
rs.status()
{
"set" : "Mgo_mt",
"date" : ISODate("2019-03-28T10:35:29.257Z"),
"myState" : 2,
"term" : NumberLong(2),
"syncingTo" : "127.0.0.1:27018",
"heartbeatIntervalMillis" : NumberLong(2000),
"members" : [
{
"_id" : 1,
"name" : "127.0.0.1:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 176,
"optime" : {
"ts" : Timestamp(1553768702, 1),
"t" : NumberLong(2)
},
"optimeDate" : ISODate("2019-03-28T10:25:02Z"),
"syncingTo" : "127.0.0.1:27018",
"configVersion" : 2,
"self" : true
},
{
"_id" : 2,
"name" : "127.0.0.1:27018",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 174,
"optime" : {
"ts" : Timestamp(1553768702, 1),
"t" : NumberLong(2)
},
"optimeDate" : ISODate("2019-03-28T10:25:02Z"),
"lastHeartbeat" : ISODate("2019-03-28T10:35:28.488Z"),
"lastHeartbeatRecv" : ISODate("2019-03-28T10:35:28.198Z"),
"pingMs" : NumberLong(0),
"electionTime" : Timestamp(1553768701, 1),
"electionDate" : ISODate("2019-03-28T10:25:01Z"),
"configVersion" : 2
},
{
"_id" : 3,
"name" : "127.0.0.1:27019",
"health" : 1,
"state" : 7,
"stateStr" : "ARBITER",
"uptime" : 174,
"lastHeartbeat" : ISODate("2019-03-28T10:35:28.486Z"),
"lastHeartbeatRecv" : ISODate("2019-03-28T10:35:27.125Z"),
"pingMs" : NumberLong(0),
"configVersion" : 2
}
],
"ok" : 1
}
此时可以配合keepalived和headbeaart实现vip切换