文章目录
接上一篇博文整理—》
6. MongoDB复制集RS(ReplicationSet)
6.1 基本原理
基本构成是1主2从的结构,自带互相监控投票机制(Raft(MongoDB) Paxos(mysql MGR 用的是变种))
如果发生主库宕机,复制集内部会进行投票选举,选择一个新的主库替代原有主库对外提供服务。同时复制集会自动通知
客户端程序,主库已经发生切换了。应用就会连接到新的主库。
6.2 Replication Set配置过程详解
6.2.1 规划
三个以上的mongodb节点(或多实例)
6.2.2 环境准备
1. 多个端口:
28017、28018、28019、28020
2. 多套目录:
su - mongod
mkdir -p /mongodb/28017/conf /mongodb/28017/data /mongodb/28017/log
mkdir -p /mongodb/28018/conf /mongodb/28018/data /mongodb/28018/log
mkdir -p /mongodb/28019/conf /mongodb/28019/data /mongodb/28019/log
mkdir -p /mongodb/28020/conf /mongodb/28020/data /mongodb/28020/log
3. 多套配置文件
/mongodb/28017/conf/mongod.conf
/mongodb/28018/conf/mongod.conf
/mongodb/28019/conf/mongod.conf
/mongodb/28020/conf/mongod.conf
4. 配置文件内容
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.0.51,127.0.0.1
port: 28017
replication:
oplogSizeMB: 2048 #日志最大容量
replSetName: my_repl
EOF
\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 's#28017#28018#g' /mongodb/28018/conf/mongod.conf -i
sed 's#28017#28019#g' /mongodb/28019/conf/mongod.conf -i
sed 's#28017#28020#g' /mongodb/28020/conf/mongod.conf -i
5. 启动多个实例备用
[mongod@db01 ~]$ mongod -f /mongodb/28017/conf/mongod.conf
about to fork child process, waiting until server is ready for connections.
forked process: 3034
child process started successfully, parent exiting
[mongod@db01 ~]$ mongod -f /mongodb/28018/conf/mongod.conf
about to fork child process, waiting until server is ready for connections.
forked process: 3063
child process started successfully, parent exiting
[mongod@db01 ~]$ mongod -f /mongodb/28019/conf/mongod.conf
about to fork child process, waiting until server is ready for connections.
forked process: 3092
child process started successfully, parent exiting
[mongod@db01 ~]$ mongod -f /mongodb/28020/conf/mongod.conf
about to fork child process, waiting until server is ready for connections.
forked process: 3121
child process started successfully, parent exiting
[mongod@db01 ~]$ 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 3034/mongod
tcp 0 0 10.0.0.51:28017 0.0.0.0:* LISTEN 3034/mongod
tcp 0 0 127.0.0.1:28018 0.0.0.0:* LISTEN 3063/mongod
tcp 0 0 10.0.0.51:28018 0.0.0.0:* LISTEN 3063/mongod
tcp 0 0 127.0.0.1:28019 0.0.0.0:* LISTEN 3092/mongod
tcp 0 0 10.0.0.51:28019 0.0.0.0:* LISTEN 3092/mongod
tcp 0 0 127.0.0.1:28020 0.0.0.0:* LISTEN 3121/mongod
tcp 0 0 10.0.0.51:28020 0.0.0.0:* LISTEN 3121/mongod
unix 2 [ ACC ] STREAM LISTENING 42006 3034/mongod /tmp/mongodb-28017.sock
unix 2 [ ACC ] STREAM LISTENING 42017 3063/mongod /tmp/mongodb-28018.sock
unix 2 [ ACC ] STREAM LISTENING 42031 3092/mongod /tmp/mongodb-28019.sock
unix 2 [ ACC ] STREAM LISTENING 42048 3121/mongod /tmp/mongodb-28020.sock
6.3 配置普通复制集:
1主2从,从库普通从库
[mongod@db01 ~]$ 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'}]
... }
{
"_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"
}
]
}
> rs.initiate(config)
{
"ok" : 1,
"operationTime" : Timestamp(1578626170, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1578626170, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
my_repl:SECONDARY>
my_repl:PRIMARY>
my_repl:PRIMARY>
my_repl:PRIMARY>
查询复制集状态
my_repl:PRIMARY> rs.status();
{
"set" : "my_repl",
"date" : ISODate("2020-01-10T03:17:27.739Z"),
"myState" : 1,
"term" : NumberLong(1),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1578626243, 1),
"t" : NumberLong(1)
},
"readConcernMajorityOpTime" : {
"ts" : Timestamp(1578626243, 1),
"t" : NumberLong(1)
},
"appliedOpTime" : {
"ts" : Timestamp(1578626243, 1),
"t" : NumberLong(1)
},
"durableOpTime" : {
"ts" : Timestamp(1578626243, 1),
"t" : NumberLong(1)
}
},
"members" : [
{
"_id" : 0,
"name" : "10.0.0.51:28017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 174,
"optime" : {
"ts" : Timestamp(1578626243, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2020-01-10T03:17:23Z"),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "could not find member to sync from",
"electionTime" : Timestamp(1578626182, 1),
"electionDate" : ISODate("2020-01-10T03:16:22Z"),
"configVersion" : 1,
"self" : true,
"lastHeartbeatMessage" : ""
},
{
"_id" : 1,
"name" : "10.0.0.51:28018",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 77,
"optime" : {
"ts" : Timestamp(1578626243, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1578626243, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2020-01-10T03:17:23Z"),
"optimeDurableDate" : ISODate("2020-01-10T03:17:23Z"),
"lastHeartbeat" : ISODate("2020-01-10T03:17:26.070Z"),
"lastHeartbeatRecv" : ISODate("2020-01-10T03:17:26.844Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "10.0.0.51:28017",
"syncSourceHost" : "10.0.0.51:28017",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 1
},
{
"_id" : 2,
"name" : "10.0.0.51:28019",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 77,
"optime" : {
"ts" : Timestamp(1578626243, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1578626243, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2020-01-10T03:17:23Z"),
"optimeDurableDate" : ISODate("2020-01-10T03:17:23Z"),
"lastHeartbeat" : ISODate("2020-01-10T03:17:26.070Z"),
"lastHeartbeatRecv" : ISODate("2020-01-10T03:17:26.836Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "10.0.0.51:28017",
"syncSourceHost" : "10.0.0.51:28017",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 1
}
],
"ok" : 1,
"operationTime" : Timestamp(1578626243, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1578626243, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
my_repl:PRIMARY>
6.4 1主1从1个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)
6.5 复制集管理操作
6.5.1 查看复制集状态
1. rs.status(); //查看整体复制集状态
2. rs.isMaster(); // 查看当前是否是主节点
3. rs.conf(); //查看复制集配置信息
my_repl:PRIMARY> rs.conf()
{
"_id" : "my_repl",
"version" : 1,
"protocolVersion" : NumberLong(1),
"members" : [
{
"_id" : 0,
"host" : "10.0.0.51:28017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0), #类似于延时从库
"votes" : 1
},
{
"_id" : 1,
"host" : "10.0.0.51:28018",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 2,
"host" : "10.0.0.51:28019",
"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("5e17ec7a5506d8f4ad899583")
}
}
6.5.2 添加删除节点
rs.remove("ip:port"); // 删除一个节点
rs.add("ip:port"); // 新增从节点
rs.addArb("ip:port"); // 新增仲裁节点
例子:
添加 arbiter节点
1、连接到主节点
[mongod@db01 ~]$ mongo --port 28018 admin
2、添加仲裁节点
my_repl:PRIMARY> rs.addArb("10.0.0.51:28020")
{
"ok" : 1,
"operationTime" : Timestamp(1578626917, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1578626917, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
3、查看节点状态
my_repl:PRIMARY> rs.isMaster()
{
"hosts" : [
"10.0.0.51:28017",
"10.0.0.51:28018",
"10.0.0.51:28019"
],
"arbiters" : [
"10.0.0.51:28020"
],
"setName" : "my_repl",
"setVersion" : 2,
"ismaster" : true,
"secondary" : false,
"primary" : "10.0.0.51:28017",
"me" : "10.0.0.51:28017",
"electionId" : ObjectId("7fffffff0000000000000001"),
"lastWrite" : {
"opTime" : {
"ts" : Timestamp(1578626917, 1),
"t" : NumberLong(1)
},
"lastWriteDate" : ISODate("2020-01-10T03:28:37Z"),
"majorityOpTime" : {
"ts" : Timestamp(1578626917, 1),
"t" : NumberLong(1)
},
"majorityWriteDate" : ISODate("2020-01-10T03:28:37Z")
},
"maxBsonObjectSize" : 16777216,
"maxMessageSizeBytes" : 48000000,
"maxWriteBatchSize" : 100000,
"localTime" : ISODate("2020-01-10T03:28:46.949Z"),
"logicalSessionTimeoutMinutes" : 30,
"minWireVersion" : 0,
"maxWireVersion" : 6,
"readOnly" : false,
"ok" : 1,
"operationTime" : Timestamp(1578626917, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1578626917, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
rs.remove("ip:port"); // 删除一个节点
例子:
my_repl:PRIMARY> rs.remove("10.0.0.51:28019");
{
"ok" : 1,
"operationTime" : Timestamp(1578627065, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1578627065, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
my_repl:PRIMARY> rs.isMaster() #查询
{
"hosts" : [
"10.0.0.51:28017",
"10.0.0.51:28018"
],
rs.add("ip:port"); // 新增从节点
例子:
my_repl:PRIMARY> rs.add("10.0.0.51:28019")
{ "ok" : 1 }
my_repl:PRIMARY> rs.isMaster()
6.5.3 特殊从节点
1. 介绍:
arbiter节点:主要负责选主过程中的投票,但是不存储任何数据,也不提供任何服务
hidden节点:隐藏节点,不参与选主,也不对外提供服务。
delay节点:延时节点,数据落后于主库一段时间,因为数据是延时的,也不应该提供服务或参与选主,所以通常会配合hidden(隐藏)
一般情况下会将delay+hidden一起配置使用
2. 配置延时节点(一般延时节点也配置成hidden)
cfg=rs.conf()
cfg.members[3].priority=0 #修改3号节点的值
cfg.members[3].hidden=true #隐藏
cfg.members[3].slaveDelay=120 #延时
my_repl:PRIMARY> rs.reconfig(cfg)
{
"ok" : 1,
"operationTime" : Timestamp(1578628124, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1578628124, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
my_repl:PRIMARY> rs.conf(); #查看修改后的信息
{
"_id" : 4,
"host" : "10.0.0.51:28019",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : true,
"priority" : 0,
"tags" : {
},
"slaveDelay" : NumberLong(120),
"votes" : 1
}
注意:节点号必须仔细查看,是按照顺序进行排列的,需要修改哪个按顺序数即可
取消以上配置
cfg=rs.conf()
cfg.members[2].priority=1
cfg.members[2].hidden=false
cfg.members[2].slaveDelay=0
rs.reconfig(cfg)
配置成功后,通过以下命令查询配置后的属性
rs.conf();
6.5.4 副本集其他操作命令
查看副本集的配置信息
admin> rs.conf()
查看副本集各成员的状态
admin> rs.status()
++++++++++++++++++++++++++++++++++++++++++++++++
--副本集角色切换(不要人为随便操作)
admin> rs.stepDown()
注:
admin> rs.freeze(300) //锁定从,使其不会转变成主库
freeze()和stepDown单位都是秒。
+++++++++++++++++++++++++++++++++++++++++++++
设置副本节点可读:在副本节点执行
admin> rs.slaveOk()
eg:
admin> use app
switched to db app
app> db.createCollection('a')
{ "ok" : 0, "errmsg" : "not master", "code" : 10107 }
查看副本节点(监控主从延时)
admin> rs.printSlaveReplicationInfo()
source: 192.168.1.22:27017
syncedTo: Thu May 26 2016 10:28:56 GMT+0800 (CST)
0 secs (0 hrs) behind the primary