一、Replica Set 集群分为两种架构:
- 奇数个节点构成Replica Set,所有节点拥有数据集。最小架构: 1个Primary节点,2个Secondary节点
- 偶数个节点 一个仲裁节点 构成的Replica Set,节点拥有数据集,仲裁节点仅参与仲裁选举出Primary节点。 最小架构:1个Primary节点,1个Secondary节点,1个Arbiter节点
接下来就以3台服务器为例,部署具有仲裁的框架。
IP地址 | 操作系统版本 | MongoDB版本 | 端口 | 功能 |
---|---|---|---|---|
10.10.18.10 | CentOS7.5 | 4.0 | 27017 | Primary |
10.10.18.11 | Centos7.5 | 4.0 | 27017 | Secondary |
10.10.18.12 | Centos7.5 | 4.0 | 27017 | Arbiter |
二、安装部署(请访问 "MongoDB安装")https://www.linuxidc.com/Linux/2019-07/159249.htm
Primary的配置文件:
代码语言:javascript复制systemLog:
destination: file
path: "/data/mongodb/log/mongod.log"
logAppend: true
storage:
dbPath: "/data/mongodb/data"
journal:
enabled: true
wiredTiger:
engineConfig:
cacheSizeGB: 2
processManagement:
fork: true
pidFilePath: "/data/mongodb/pid/m.pid"
net:
bindIp: 10.10.18.10
port: 27017
代码语言:javascript复制replication:
replSetName: "rs0"
Secondary的配置文件
代码语言:javascript复制systemLog:
destination: file
path: "/data/mongodb/log/mongod.log"
logAppend: true
storage:
dbPath: "/data/mongodb/data"
journal:
enabled: true
wiredTiger:
engineConfig:
cacheSizeGB: 2
processManagement:
fork: true
pidFilePath: "/data/mongodb/pid/m.pid"
net:
bindIp: 10.10.18.11
port: 27017
replication:
replSetName: "rs0"
Arbiter的配置文件
代码语言:javascript复制systemLog:
destination: file
path: "/data/mongodb/log/mongod.log"
logAppend: true
storage:
dbPath: "/data/mongodb/data"
journal:
enabled: true
wiredTiger:
engineConfig:
cacheSizeGB: 2
processManagement:
fork: true
pidFilePath: "/data/mongodb/pid/m.pid"
net:
bindIp: 10.10.18.12
port: 27017
replication:
replSetName: "rs0"
启动三台服务器上的mongdb
代码语言:javascript复制mongod -f /data/mongodb/mongod.conf
关闭进程
代码语言:javascript复制 mongod -f /data/mongodb/mongod.conf --shutdown
三、配置Replica Set
登录三台服务器中任意一台,登录mongo(如果报错就将配置文件中:security 内容暂时先去掉)
代码语言:javascript复制mongo --host 10.10.18.10
代码语言:javascript复制>cfg={ _id:"rs0",members:[{_id:0,host:'10.10.18.10:27017',priority:1},{_id:1,host:'10.10.18.11:27017',priority:1},{_id:2,host:'10.10.18.12:27017',arbiterOnly:true}] };
>rs.initiate(cfg)
查看Replica Set配置
代码语言:javascript复制> rs.conf()
{ "_id" : "rs0", "version" : 1, "protocolVersion" : NumberLong(1), "writeConcernMajorityJournalDefault" : true, "members" : [ { "_id" : 0, "host" : "10.10.18.10:27017", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : {
}, "slaveDelay" : NumberLong(0), "votes" : 1 }, { "_id" : 1, "host" : "10.10.18.11:27017", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : {
}, "slaveDelay" : NumberLong(0), "votes" : 1 }, { "_id" : 2, "host" : "10.10.18.12:27017", "arbiterOnly" : true, "buildIndexes" : true, "hidden" : false, "priority" : 0, "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("5cff76e5e57e23a5bc7054e2") } }
四、验证Replica Set
在Primary中插入数据
代码语言:javascript复制rs0:PRIMARY> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
rs0:PRIMARY> db.users.insertOne(
... {
... name:"sue",
... age: 26,
... status:"pending"
... })
{
"acknowledged" : true,
"insertedId" : ObjectId("5cff79e8993e70290a081d04")
}
rs0:PRIMARY> db.users.find() { "_id" : ObjectId("5cff79e8993e70290a081d04"), "name" : "sue", "age" : 26, "status" : "pending" }
在Secondary中,默认是不允许读
代码语言:javascript复制rs0:SECONDARY> db.users.find()
Error: error: {
"operationTime" : Timestamp(1560247181, 1),
"ok" : 0,
"errmsg" : "not master and slaveOk=false",
"code" : 13435,
"codeName" : "NotMasterNoSlaveOk",
"$clusterTime" : {
"clusterTime" : Timestamp(1560247181, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
五、创建用户 https://www.linuxidc.com/Linux/2019-07/159238.htm
六、故障模拟
停止Primary上的mongo进程,在Secondary上登录mongo查看
代码语言:javascript复制mongo --host 10.10.18.11
rs0:PRIMARY> db.users.find()
{ "_id" : ObjectId("5cff79e8993e70290a081d04"), "name" : "sue", "age" : 26, "status" : "pending" }
发现原Secondary变成Primary,并且可以进行查询。
开启原Primary服务器上的mongo进程,该服务器变成了Secondary。
七、数据备份和恢复
mongodump从MongoDB中读取数据,保存为BSON文件,mongorestore读取BSON文件恢复到MongoDB中。适用于小型MongoDB的备份和恢复。
mongodump备份的时候只备份MongoDB中的文档,使用mongorestore恢复之后需要重建索引
代码语言:javascript复制mongodump --host 10.10.18.11 --port 27017 --username myUserAdmin --password abc123 --gzip --out /data/mongobak/$(date %F)
注:--oplog 表示备份的时候oplog.bson文件,存放在dump开始 到 dump结束之间所有的oplog。
根据前面的备份恢复到一个新的Replica Set集群中其中一台服务器上。
恢复
恢复的过程中,不要启用认证。否则在将其他机器加入到Replica Set集群中来的时候,会出现无法认证的问题。
1、首先在一台服务器上开启一个干净mongo服务(无任何数据),做为 Primary
mongd.conf配置文件内容
代码语言:javascript复制systemLog:
destination: file
path: "/data/mongodb/log/mongod.log"
logAppend: true
storage:
dbPath: "/data/mongodb/data"
journal:
enabled: true
wiredTiger:
engineConfig:
cacheSizeGB: 2
processManagement:
fork: true
pidFilePath: "/data/mongodb/pid/mongod.pid"
net:
bindIp: 10.10.18.10
port: 27017
replication:
replSetName: "rs0"
2、开启mongod服务
代码语言:javascript复制/data/mongodb/bin/mongod -f /data/mongodb/mongod.conf
3、创建单个Replica Set
登录mongo,然后创建单个Replica Set
代码语言:javascript复制mongo --host 10.10.18.10
> cfg={_id:"rs0",members:[{_id:0,host:'10.10.18.10:27017',priority:1}]}
代码语言:javascript复制> rs.initiate(cfg)
创建结果:
{ "ok" : 1, "operationTime" : Timestamp(1560394449, 1), "$clusterTime" : { "clusterTime" : Timestamp(1560394449, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } } }
创建好了之后,就可以查看当前的数据库
代码语言:javascript复制rs0:SECONDARY> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
可以发现,目前就三个基本的数据库。
4、恢复数据
代码语言:javascript复制mongorestore --host 10.10.18.10 --port 27017 --gzip /data/mongobak/2019-06-12
结果
2019-06-13T10:55:33.817 0800 preparing collections to restore from 2019-06-13T10:55:33.829 0800 reading metadata for admin.test from /data/mongobak/2019-06-12/admin/test.metadata.json.gz 2019-06-13T10:55:33.832 0800 reading metadata for test.users from /data/mongobak/2019-06-12/test/users.metadata.json.gz 2019-06-13T10:55:33.834 0800 reading metadata for reporting.reporting from /data/mongobak/2019-06-12/reporting/reporting.metadata.json.gz 2019-06-13T10:55:33.841 0800 reading metadata for admin.reporting from /data/mongobak/2019-06-12/admin/reporting.metadata.json.gz 2019-06-13T10:55:33.861 0800 restoring test.users from /data/mongobak/2019-06-12/test/users.bson.gz 2019-06-13T10:55:34.085 0800 restoring admin.test from /data/mongobak/2019-06-12/admin/test.bson.gz 2019-06-13T10:55:34.123 0800 no indexes to restore 2019-06-13T10:55:34.123 0800 finished restoring test.users (1 document) 2019-06-13T10:55:34.123 0800 restoring admin.reporting from /data/mongobak/2019-06-12/admin/reporting.bson.gz 2019-06-13T10:55:34.175 0800 restoring reporting.reporting from /data/mongobak/2019-06-12/reporting/reporting.bson.gz 2019-06-13T10:55:34.230 0800 no indexes to restore 2019-06-13T10:55:34.230 0800 finished restoring admin.test (2 documents) 2019-06-13T10:55:34.233 0800 no indexes to restore 2019-06-13T10:55:34.233 0800 finished restoring reporting.reporting (1 document) 2019-06-13T10:55:34.234 0800 no indexes to restore 2019-06-13T10:55:34.234 0800 finished restoring admin.reporting (1 document) 2019-06-13T10:55:34.234 0800 restoring users from /data/mongobak/2019-06-12/admin/system.users.bson.gz 2019-06-13T10:55:34.312 0800 done
恢复完成,在登录mongo查看,恢复数据库的情况。
rs0:PRIMARY> show dbs admin 0.000GB config 0.000GB local 0.000GB reporting 0.000GB test 0.000GB rs0:PRIMARY> use test switched to db test rs0:PRIMARY> show collections users rs0:PRIMARY> db.users.find() { "_id" : ObjectId("5cff79e8993e70290a081d04"), "name" : "sue", "age" : 26, "status" : "pending" }
可以看出之前的记录已经恢复了。
注意:如果备份时,MongoDB是拥有用户名和密码才能进行登录的,在恢复之后,用户名和密码也是可以使用的。如果需要在使用认证登录,需要将下面信息添加的配置文件mongod.conf:
代码语言:javascript复制security:
keyFile: "/data/mongodb/keyfile"
authorization: "enabled"
然后重启mongo服务。
5、关闭刚恢复的MongoDB,将数据目录同步到另一台服务器上,作为Secondary
通过之前,确认该台服务器上的mongo是无任何数据。将Primary服务上的 /data/mongodb/data 同步到 Secondary服务器上 /data/mongodb/data
6、依次开启Primary、Secondary、Arbiter的mongo服务
7、在Primary服务器上,将Secondary、Arbiter加入到Replica Set集群中来
查看当前Replica Set集群的配置
代码语言:javascript复制rs0:PRIMARY> rs.conf()
{
"_id" : "rs0",
"version" : 1,
"protocolVersion" : NumberLong(1),
"writeConcernMajorityJournalDefault" : true,
"members" : [
{
"_id" : 0,
"host" : "10.10.18.10: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("5d01bad15dfd3f294d147b36")
}
}
可以看到当前Replica Set集群中就一台服务器
将Secondary、Arbiter加入到Replica Set集群中
代码语言:javascript复制rs0:PRIMARY> rs.add(
... {
... _id: 1,
... host:'10.10.18.11:27017',
... priority:1
... }
... )
{
"ok" : 1,
"operationTime" : Timestamp(1560397822, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1560397822, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
rs0:PRIMARY> rs.add(
... {
... _id: 2,
... host:'10.10.18.12:27017',
... arbiterOnly:true
... }
... )
{
"ok" : 1,
"operationTime" : Timestamp(1560397830, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1560397830, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
再次查看状态:
代码语言:javascript复制rs0:PRIMARY> rs.conf()
{
"_id" : "rs0",
"version" : 3,
"protocolVersion" : NumberLong(1),
"writeConcernMajorityJournalDefault" : true,
"members" : [
{
"_id" : 0,
"host" : "10.10.18.10:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 1,
"host" : "10.10.18.11:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 2,
"host" : "10.10.18.12:27017",
"arbiterOnly" : true,
"buildIndexes" : true,
"hidden" : false,
"priority" : 0,
"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("5d01bad15dfd3f294d147b36")
}
}
加入成功。
开启认证访问
在三台服务器的配置文件中添加:
代码语言:javascript复制security:
keyFile: "/data/mongodb/keyfile"
authorization: "enabled"
然后依次关闭:Arbiter Secondary Primary
依次开启:Primary Secondary Arbiter
代码语言:javascript复制security:
keyFile: "/data/mongodb/keyfile"
authorization: "enabled"