1、准备三台服务器
192.168.9.146 mongo146
192.168.9.145 mongo145
192.168.9.147 mongo147
各自安装MongoDB,过程此处省略。
2、创建数据目录
在三台服务器上各自
创建数据目录(注:如果在同一台机器上,数据目录要区分:mkdir -p /data{1,2,3})
#mongo146
mkdir -p /data/db
#mongo145
mkdir -p /data/db
#mongo147
mkdir -p /data/db
3、准备配置文件
三台服务器下的/data/db/mongod.conf文件是一模一样
的(注:如果在同一台机器上,path和dbPath修改为对应的数据路径即可,端口也需不一样
,而三台服务器不用考虑,配置文件一模一样即可)
# /data/db/mongod.conf
systemLog:
destination: file
path: /data/db/mongod.log # 日志文件路径
logAppend: true
storage:
dbPath: /data/db # 数据目录
net:
bindIp: 0.0.0.0
port: 28017 # 端口
replication:
replSetName: rs0
processManagement:
fork: true
4、配置完成,执行进程
将三台服务器分别启动执行进程
mongod -f /data/db/mongod.conf
mongod -f /data/db/mongod.conf
mongod -f /data/db/mongod.conf
5、配置复制集
随便进入一台mongo shell:
mongo --port 28017
创建复制集:
rs.initiate({
_id: "rs0",
members: [{
_id: 0,
host: "mongo145:28017"
},{
_id: 1,
host: "mongo146:28017"
},{
_id: 2,
host: "mongo147:28017"
}]
})
查看复制集状态:<复制集为一主(rs0:PRIMARY)二从(rs0:SECONDARY)>
rs.status()
// 输出信息
{
"set" : "rs0",
"date" : ISODate("2019-11-03T09:27:49.555Z"),
"myState" : 1,
"term" : NumberLong(1),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1572773266, 1),
"t" : NumberLong(1)
},
"appliedOpTime" : {
"ts" : Timestamp(1572773266, 1),
"t" : NumberLong(1)
},
"durableOpTime" : {
"ts" : Timestamp(1572773266, 1),
"t" : NumberLong(1)
}
},
"members" : [
{
"_id" : 0,
"name" : "mongo145:28017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 208,
"optime" : {
"ts" : Timestamp(1572773266, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2019-11-03T09:27:46Z"),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "could not find member to sync from",
"electionTime" : Timestamp(1572773214, 1),
"electionDate" : ISODate("2019-11-03T09:26:54Z"),
"configVersion" : 1,
"self" : true,
"lastHeartbeatMessage" : ""
},
{
"_id" : 1,
"name" : "mongo146:28017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 66,
"optime" : {
"ts" : Timestamp(1572773266, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1572773266, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2019-11-03T09:27:46Z"),
"optimeDurableDate" : ISODate("2019-11-03T09:27:46Z"),
"lastHeartbeat" : ISODate("2019-11-03T09:27:48.410Z"),
"lastHeartbeatRecv" : ISODate("2019-11-03T09:27:47.875Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "mongo146:28017",
"syncSourceHost" : "mongo146:28017",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 1
},
{
"_id" : 2,
"name" : "mongo147:28017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 66,
"optime" : {
"ts" : Timestamp(1572773266, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1572773266, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2019-11-03T09:27:46Z"),
"optimeDurableDate" : ISODate("2019-11-03T09:27:46Z"),
"lastHeartbeat" : ISODate("2019-11-03T09:27:48.410Z"),
"lastHeartbeatRecv" : ISODate("2019-11-03T09:27:47.929Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "mongo147:28017",
"syncSourceHost" : "mongo146:28017",
"syncSourceId" : 1,
"infoMessage" : "",
"configVersion" : 1
}
],
"ok" : 1
}
6、测试Mongodb副本集数据复制功能
有两种方法实现从机的查询(均在副本节点运行):
第一种方法:db.getMongo().setSlaveOk();
第二种方法:rs.slaveOk();
但是这种方式有一个缺点就是,下次再通过mongo进入实例的时候,查询仍然会报错,为此可以通过下列方式
vi ~/.mongorc.js,增加一行rs.slaveOk();
这样的话以后每次通过mongo命令进入都可以查询了
vi ~/.mongorc.js
#写入
rs.slaveOk();
#application.yml
data:
mongodb:
uri: mongodb://192.168.9.145:28017,192.168.9.146:28017,192.168.9.147:28017/test?slaveOk=true&replicaSet=rs0&write=1&readPreference=secondaryPreferred&connectTimeoutMS=300000
读参数除了secondary一共还有五个参数:`primary、primaryPreferred、secondary、secondaryPreferred、nearest`。
`primary`:默认参数,只从主节点上进行读取操作;
`primaryPreferred`:大部分从主节点上读取数据,只有主节点不可用时从secondary节点读取数据。
`secondary`:只从secondary节点上进行读取操作,存在的问题是secondary节点的数据会比primary节点数据“旧”。
`secondaryPreferred`:优先从secondary节点进行读取操作,secondary节点不可用时从主节点读取数据;
`nearest`:不管是主节点、secondary节点,从网络延迟最低的节点上读取数据。
读写分离做好后,就可以进行数据分流,减轻压力,解决了"主节点的读写压力过大如何解决?"这个问题。不过当副本节点增多时,主节点的复制压力会加大有什么办法解决吗?基于这个问题,Mongodb已有了相应的解决方案 - 引用仲裁节点:
在Mongodb副本集中,仲裁节点不存储数据,只是负责故障转移的群体投票,这样就少了数据复制的压力。看起来想的很周到啊,其实不只是主节点、副本节点、仲裁节点,还有`Secondary-Only、Hidden、Delayed、Non-Voting`,其中:
`Secondary-Only`:不能成为primary节点,只能作为secondary副本节点,防止一些性能不高的节点成为主节点。
`Hidden`:这类节点是不能够被客户端制定IP引用,也不能被设置为主节点,但是可以投票,一般用于备份数据。
`Delayed`:可以指定一个时间延迟从primary节点同步数据。主要用于备份数据,如果实时同步,误删除数据马上同步到从节点,恢复又恢复不了。
`Non-Voting`:没有选举权的secondary节点,纯粹的备份数据节点。