MongoDB复制集RS(ReplicationSet)*****
![](D:\data\Sync-data\simon\学习笔记\Mysql 笔记\MySql-DBA\Mongodb\NoSQL-Mongodb-04-复制集RS(ReplicationSet).assets\复制集RS架构图-01.png)
基本原理
基本构成是1主2从的结构,自带互相监控投票机制(Raft 分布式一致性协议(MongoDB) Paxos(mysql MGR 用的是变种))
如果发生主库宕机,复制集内部会进行投票选举,选择一个新的主库替代原有主库对外提供服务。同时复制集会自动通知
客户端程序,主库已经发生切换了。应用就会连接到新的主库。
集群节点 也会有专用日志:OPLOG
通过OPLOG日志,实现各节点之间的数据同步
OPLOG会自带类似GTID的能力,只不过OPLOG是基于时间戳的进行控制,类似MySQL中的binlog
OPLOG不是以文件形式存储,是存储在数据库的一个 集合/表 里
节点之间自动心跳检测
如果主节点宕机,会自动选新主并重构主从关系,实现FailOver故障转移
Raft Paxos 分布式一致性协议
在真正事务commit提交之前,数据或日志已经达到各个node节点,进行决议之后再决定是否提交还是回滚。日志的传输,是在总体执行前的动作。
规划
默认1主多从,建议1主2从,满足投票半数
三个以上的mongodb节点(或多实例)
环境准备
多个端口
28017、28018、28019、28020
多套目录
su - mongod
mkdir -p /mongodb/280{17..20}/{conf,data,log}
多套配置文件
/mongodb/28017/conf/mongod.conf
/mongodb/28018/conf/mongod.conf
/mongodb/28019/conf/mongod.conf
/mongodb/28020/conf/mongod.conf
配置文件内容
cat > /mongodb/28017/conf/mongod.conf <<EOF
systemLog:
destination: file
path: /mongodb/28017/log/mongodb.log
logAppend: true
storage:
journal:
enabled: true
dbPath: /mongodb/28017/data
directoryPerDB: true
#engine: wiredTiger
wiredTiger:
engineConfig:
cacheSizeGB: 1 #缓冲区大小
directoryForIndexes: true #目录索引
collectionConfig:
blockCompressor: zlib #压缩
indexConfig:
prefixCompression: true
processManagement:
fork: true
net:
bindIp: 10.0.50.61,127.0.0.1
port: 28017
replication:
oplogSizeMB: 2048 #oplog 大小为2G,滚动使用,空间不够,会覆盖之前的记录
replSetName: my_repl # 复制集的name
EOF
说明:
1、3.x版本以上默认 WT(wiredTiger) 引擎,相当于MySQL 的Innodb,支持事务,文档锁,redo功能,多缓冲区支持等等
2、早起2.x版本中,默认的是MMAPv1引擎,相当于MySQL的MyISAM引擎
\cp /mongodb/28017/conf/mongod.conf /mongodb/28018/conf/
\cp /mongodb/28017/conf/mongod.conf /mongodb/28019/conf/
\cp /mongodb/28017/conf/mongod.conf /mongodb/28020/conf/
sed -i 's#28017#28018#g' /mongodb/28018/conf/mongod.conf
sed -i 's#28017#28019#g' /mongodb/28019/conf/mongod.conf
sed -i 's#28017#28020#g' /mongodb/28020/conf/mongod.conf
chown -R mongod:mongod /mongodb
启动多个实例备用
mongod -f /mongodb/28017/conf/mongod.conf
mongod -f /mongodb/28018/conf/mongod.conf
mongod -f /mongodb/28019/conf/mongod.conf
mongod -f /mongodb/28020/conf/mongod.conf
netstat -lnp|grep 280
[mongod@mysql-node01 ~]$ netstat -lnp|grep 280
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
tcp 0 0 127.0.0.1:28017 0.0.0.0:* LISTEN 9476/mongod
tcp 0 0 10.0.50.61:28017 0.0.0.0:* LISTEN 9476/mongod
tcp 0 0 127.0.0.1:28018 0.0.0.0:* LISTEN 9509/mongod
tcp 0 0 10.0.50.61:28018 0.0.0.0:* LISTEN 9509/mongod
tcp 0 0 127.0.0.1:28019 0.0.0.0:* LISTEN 9542/mongod
tcp 0 0 10.0.50.61:28019 0.0.0.0:* LISTEN 9542/mongod
tcp 0 0 127.0.0.1:28020 0.0.0.0:* LISTEN 9575/mongod
tcp 0 0 10.0.50.61:28020 0.0.0.0:* LISTEN 9575/mongod
unix 2 [ ACC ] STREAM LISTENING 483181 9476/mongod /tmp/mongodb-28017.sock
unix 2 [ ACC ] STREAM LISTENING 483535 9509/mongod /tmp/mongodb-28018.sock
unix 2 [ ACC ] STREAM LISTENING 483197 9542/mongod /tmp/mongodb-28019.sock
unix 2 [ ACC ] STREAM LISTENING 483208 9575/mongod /tmp/mongodb-28020.sock
[mongod@mysql-node01 ~]$
配置普通复制集
1主2从,从库普通从库
mongo --port 28017 admin
config = {_id: 'my_repl', members: [
{_id: 0, host: '10.0.50.61:28017'},
{_id: 1, host: '10.0.50.61:28018'},
{_id: 2, host: '10.0.50.61:28019'}
]
}
rs.initiate(config)
> rs.initiate(config)
{
"ok" : 1,
"operationTime" : Timestamp(1603515267, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1603515267, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
my_repl:OTHER>
查询复制集状态
rs.status();
Replica Set Arbiter
上述普通复制集结构,主节点要向其他节点传输OPLOG,会承担较大的IO负载,对节点性能有影响,为了减少这种影响,MongoDB官方给出 Replica Set Arbiter
结构,结构图:
![](D:\data\Sync-data\simon\学习笔记\Mysql 笔记\MySql-DBA\Mongodb\NoSQL-Mongodb-04-复制集RS(ReplicationSet).assets\ReplicaSet-Arbiter.png)
在这个结构中,Arbiter节点,不参与数据复制,也不参与故障时的选主,只负责投票,用以打破投票平局的情况。
官方文档说明:
https://docs.mongodb.com/v3.6/core/replica-set-arbiter/index.html
1主 1从 1个arbiter
方法1:
# 推荐,在搭建MongoDB 复制集过程中,直接把Arbiter节点做好。
mongo -port 28017 admin
config = {_id: 'my_repl', members: [
{_id: 0, host: '10.0.0.51:28017'},
{_id: 1, host: '10.0.0.51:28018'},
{_id: 2, host: '10.0.0.51:28019',"arbiterOnly":true}]
}
rs.initiate(config)
方法2:
将已有节点28019,替换为Arbiter节点
mongo -port 28017 admin
# 把28019节点从复制集中移除
rs.remove("10.0.50.61:28019")
my_repl:PRIMARY> rs.remove("10.0.50.61:28019")
{
"ok" : 1, # 返回为1,说明节点移除成功
"operationTime" : Timestamp(1603516687, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1603516687, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
my_repl:PRIMARY>
# 用rs.addArb命令,把28019 添加为arbiter节点
my_repl:PRIMARY>
my_repl:PRIMARY> rs.add
rs.add( rs.addArb(
my_repl:PRIMARY> rs.addArb("10.0.50.61:28019")
{
"ok" : 1,
"operationTime" : Timestamp(1603516901, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1603516901, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
my_repl:PRIMARY>
# 查看副本集状态
my_repl:PRIMARY> rs.status("member")
......
"_id" : 2,
"name" : "10.0.50.61:28019",
"health" : 0,
"state" : 8,
"stateStr" : "(not reachable/healthy)",
"uptime" : 0,
......
# 节点状态为“not reachable/healthy” 无状态
# 查看 28019端口
[mongod@mysql-node01 ~]$ ss -lntp|grep 28019
[mongod@mysql-node01 ~]$
# 被down掉了,重启28019
mongod -f /mongodb/28019/conf/mongod.conf
# 启动28019后再 登陆mongodb查看状态
my_repl:PRIMARY> rs.status("member")
......
"name" : "10.0.50.61:28019",
"health" : 1,
"state" : 7,
"stateStr" : "ARBITER",
"uptime" : 6,
......
# 添加arbiter节点完成
复制集管理操作
查看复制集状态
rs.status(); //查看整体复制集状态
rs.isMaster(); // 查看当前是否是主节点
rs.conf(); //查看复制集配置信息
添加删除节点
rs.remove("ip:port"); // 删除一个节点
rs.add("ip:port"); // 新增从节点
rs.addArb("ip:port"); // 新增仲裁节点
例子:
添加 arbiter节点
1、连接到主节点
[mongod@db03 ~]$ mongo --port 28018 admin
2、添加仲裁节点
my_repl:PRIMARY> rs.addArb("10.0.0.53:28020")
3、查看节点状态
my_repl:PRIMARY> rs.isMaster()
{
"hosts" : [
"10.0.0.53:28017",
"10.0.0.53:28018",
"10.0.0.53:28019"
],
"arbiters" : [
"10.0.0.53:28020"
],
rs.remove("ip:port"); // 删除一个节点
例子:
my_repl:PRIMARY> rs.remove("10.0.0.53:28019");
{ "ok" : 1 }
my_repl:PRIMARY> rs.isMaster()
rs.add("ip:port"); // 新增从节点
例子:
my_repl:PRIMARY> rs.add("10.0.0.53:28019")
{ "ok" : 1 }
my_repl:PRIMARY> rs.isMaster()
# 将rs.slaveOk()写入到这个.mongors.js文件中,这样,就可以让mongo-shell客户端为自动执行这个命令
echo 'rs.slaveOk()' > /root/.mongors.js
读写分离
对于MongoDB来说,主节点一般用于写数据,从节点用于读数据,且主节点也并不是固定的(当主节点宕机后会选举出一个新的主节点),所以在生产环境时客户端不能直连主节点,要配置所有节点
<mongo:mongo-client replica-set="ip1:port1,ip2:port2,ip3:port3">
<mongo:client-options read-preference="SECONDARY_PREFERRED"/>
</mongo:mongo-client>
通过read-preference参数控制读写分离方式,其类型有以下几种:
- PRIMARY(默认)
读操作都在主节点,若主节点不可用则报错。 - PRIMARY_PREFERRED
首选主节点,若主节点不可用则转移到其它从节点。 - SECONDARY
读从节点,不可用则报错。 - SECONDARY_PREFERRED(推荐)
首选从节点,若是特殊情况则在主节点读(单主节点架构)。 - NEAREST
最邻近主节点。