最简单的三节点副本集
启动服务
docker 启动
docker run -d --name rs1mon1 -v /home/mongodb/data/cs/configsvr0:/data/configdb mongo:3.6.0 --replSet rs_1 --bind_ip_all
docker run -d --name rs1mon2 -v /home/mongodb/data/cs/configsvr1:/data/configdb mongo:3.6.0 --replSet rs_1 --bind_ip_all
docker run -d --name rs1mon3 -v /home/mongodb/data/cs/configsvr2:/data/configdb mongo:3.6.0 --replSet rs_1 --bind_ip_all
docker run -d --name rs1mon1 -p 27017:27017 mongo:3.6.0 --replSet rs_1
docker run -d --name rs1mon2 -p 27017:27018 mongo:3.6.0 --replSet rs_1
docker run -d --name rs1mon3 -p 27017:27019 mongo:3.6.0 --replSet rs_1
查看ip
docker inspect rs1mon1 | grep IPAddress
docker inspect rs1mon2 | grep IPAddress
docker inspect rs1mon3 | grep IPAddress
初始化
#在正常的节点执行初始化命令,否则错误信息显示此节点没有资格
docker exec -it rs1mon1 bash
docker内执行
mongo
#在admin才能执行初始化
use admin
rs.initiate(
{
_id:“myrs”,
members:[
{_id:0,host:“192.168.158.120:27017”},
{_id:1,host:“192.168.158.121:27017”},
{_id:2,host:“192.168.158.123:27017”},
]
}
)
查看副本集状态
rs.status()
rs.conf()
db.isMaster()
易混淆的概念mongoShell command 与 database command
mongo shell command 是对一组JavaScript的API的调用,API中封装了包括但不限于database command的方法
database command中在当前库执行可以使用db.runCommand(),传入参数是一个BSON,要对admin数据库运行管理命令, 可以使用db.adminCommand(), 相当于db.getSiblingDB(“admin”).runCommand()
mongoShell command database command 意义
rs.conf() db.runCommand( { replSetGetConfig: 1 } ); 返回描述 replica set 当前配置的文档
rs.status() db.adminCommand( { replSetGetStatus: 1 } ) 返回副本集的状态。 replSetGetStatus 必须针对 admin database 运行
db.isMaster() db.runCommand( { isMaster: 1 } ); 返回描述 mongod实例角色的文档
自定义的三节点副本集
配置文件
systemLog:
destination: file
path: “/root/mongo/log/mongod.log”
logAppend: true
storage:
dbPath: “/root/mongo/data”
journal:
enabled: true
processManagement:
守护进程模式启动,默认 false
fork: true
存储mongo进程pid 不设置时不默认存储
pidFilePath: “/root/mongo/conf/mongod.pid”
net:
bindIpAll: true
port: 27017
#security:
集群中设置用户权限时必须有此文件,而且集群中所有几点的此文件都是相同的,文件权限400或600均可
keyFile: “/root/mongo/conf/access.key”
authorization: enabled
replication:
replication操作日志的最大尺寸,单位:MB。
对于64位系统,oplog默认占可用磁盘空间的5%。
oplogSizeMB: 500
复制集的名称
replSetName: myrs
读策略,默认为true:majority
enableMajorityReadConcern: false
h3c副本集版mongodb配置文件
副本集版
绑定所有ipv4的地址 默认是localhost,只绑定localhost时只能本地连接
net:
bindIp: 0.0.0.0
绑定端口
port: 3333
分析器 级别 off;slowOp;all
operationProfiling:
mode: slowOp
缓慢的操作时间阈值,以毫秒为单位
slowOpThresholdMs: 100
processManagement:
后台运行
fork: true
保存进程ID
pidFilePath: /var/run/mongodb/mongod.pid
加载时区数据库的完整路径
timeZoneInfo: /usr/share/zoneinfo
security:
启用基于角色的访问控制,默认disable
authorization: enabled
密钥文件的路径,在副本集和分片集群中用于集群内成员身份验证
keyFile: /var/lib/mongo/mongod-keyfile
设置 MongoDB Server Parameters 中描述的MongoDB参数或参数
相当于db.adminCommand( { setParameter: 1, : } )
setParameter:
设置MongoDB删除之前空闲游标的到期阈值(以毫秒为单位)
默认值:600000(即10分钟)
cursorTimeoutMillis: 600000
指定 0 或 false 以禁用localhost身份验证绕过。默认情况下启用。
只能使用配置文件中的 setParameter 选项或命令行上的 --setParameter 选项
enableLocalhostAuthBypass: false
内存限制,单位:bytes 默认值是33554432(32M)
internalQueryExecMaxBlockingSortBytes: 33554432
存储选项
storage:
数据存储目录
dbPath: /var/lib/mongo
启用或禁用持久性日志。仅当指定storage.dbPath时生效
journal:
enabled: true
systemLog:
日志输出的目标。指定 file 或 syslog
destination: file
追加日志
logAppend: true
systemLog.destination=file时指定的的保存路径
path: /var/log/mongodb/mongod.log
replication:
副本集名字
replSetName: “mongoReplicaSet-fcd4a7df”
启动命令
mongod -f /root/mongo/conf/mongod.conf
配置文件中部分参数可以在启动命令中指定,或在数据库中设置,例如下方的格式
mongod --replSet “mongoReplicaSet-fcd4a7df” --dbpath /var/lib/mongo --bind_ip 0.0.0.0 --port 3333 --fork
初始化副本集
主从仲裁-> PSA体系
rs.initiate(
{
_id:“myrs”,
members:[
{_id:0,host:“192.168.158.120:27017”},
{_id:1,host:“192.168.158.121:27017”},
{_id:2,host:“192.168.158.122:27017”,arbiterOnly:true},
]
}
)
主从隐藏
rs.initiate(
{
_id:“myrs”,
members:[
{_id:0,host:“192.168.158.120:27017”},
{_id:1,host:“192.168.158.121:27017”},
{_id:2,host:“192.168.158.123:27017”,priority: 0,hidden:true},
]
}
)
replSetGetConfig(rs.conf())部分返回值介绍
{
# 副本集名称
“_id” : “myrs”,
# 版本号
“version” : 5,
# 副本集内的成员
“members” : [
{
“_id” : 0,
“host” : “192.168.158.120: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("5cb93cd138f683231ab9390c")
}
}
replSetGetStatus(rs.status())部分返回值介绍
{
“set” : “myrs”,
“date” : ISODate(“2019-05-20T05:16:08.191Z”),
# 当前成员状态
“myState” : 1,
# 选举计数
“term” : NumberLong(27),
“syncingTo” : “”,
同步的主机名
“syncSourceHost” : “”,
同步的成员_id
“syncSourceId” : -1,
“heartbeatIntervalMillis” : NumberLong(2000),
记录复制操作记录
“optimes” : {
“lastCommittedOpTime” : {
“ts” : Timestamp(1558329361, 1),
“t” : NumberLong(27)
},
“readConcernMajorityOpTime” : {
“ts” : Timestamp(1558329361, 1),
“t” : NumberLong(27)
},
“appliedOpTime” : {
“ts” : Timestamp(1558329361, 1),
“t” : NumberLong(27)
},
“durableOpTime” : {
“ts” : Timestamp(1558329361, 1),
“t” : NumberLong(27)
}
},
“lastStableCheckpointTimestamp” : Timestamp(1558329351, 1),
“members” : [
{
“_id” : 0,
“name” : “192.168.158.120:27017”,
“health” : 1,
# 成员状态 为 0-10的数字
“state” : 2,
# state 对应的描述 共11种
“stateStr” : “SECONDARY”,
“uptime” : 17013,
“optime” : {
“ts” : Timestamp(1558329361, 1),
“t” : NumberLong(27)
},
“optimeDurable” : {
“ts” : Timestamp(1558329361, 1),
“t” : NumberLong(27)
},
“optimeDate” : ISODate(“2019-05-20T05:16:01Z”),
“optimeDurableDate” : ISODate(“2019-05-20T05:16:01Z”),
“lastHeartbeat” : ISODate(“2019-05-20T05:16:08.040Z”),
“lastHeartbeatRecv” : ISODate(“2019-05-20T05:16:07.468Z”),
“pingMs” : NumberLong(0),
“lastHeartbeatMessage” : “”,
“syncingTo” : “192.168.158.121:27017”,
“syncSourceHost” : “192.168.158.121:27017”,
“syncSourceId” : 1,
“infoMessage” : “”,
rs.conf()返回值钟的 version值
“configVersion” : 5
},
{
# 调用 rs.status()的节点部分数据已经在外层显示
“_id” : 1,
“name” : “192.168.158.121:27017”,
“health” : 1,
“state” : 1,
“stateStr” : “PRIMARY”,
“uptime” : 17184,
“optime” : {
“ts” : Timestamp(1558329361, 1),
“t” : NumberLong(27)
},
“optimeDate” : ISODate(“2019-05-20T05:16:01Z”),
“syncingTo” : “”,
“syncSourceHost” : “”,
“syncSourceId” : -1,
“infoMessage” : “”,
“electionTime” : Timestamp(1558312358, 1),
“electionDate” : ISODate(“2019-05-20T00:32:38Z”),
“configVersion” : 5,
“self” : true,
“lastHeartbeatMessage” : “”
},
],
“ok” : 1,
“operationTime” : Timestamp(1558329361, 1),
“KaTeX parse error: Expected 'EOF', got '}' at position 189: …80450") } } }̲ isMaster(db.is…clusterTime” : {
“clusterTime” : Timestamp(1558329681, 1),
“signature” : {
“hash” : BinData(0,“Nuf+9OyHegqxHRFoExv3Si8m94Y=”),
“keyId” : NumberLong(“6681438442066280450”)
}
}
}
主从切换
通过设置优先级实现
mongoShell 操作
conf = rs.conf()
conf.members[2].priority = 2
rs.reconfig(conf)
database command操作
conf = db.runCommand( { replSetGetConfig: 1 } );
conf.members[2].priority = 2
conf.version ++
db.adminCommand( { replSetReconfig: conf, force: false } );
通过primary降级实现
mongoShell操作
rs.stepDown()
database command操作
db.adminCommand( { replSetStepDown: 120, secondaryCatchUpPeriodSecs: 15, force: true } )
主从选举机制
触发条件
副本集初始化 rs.initiate()
副本集添加成员 rs.add()
主动切换,rs.reconfig(),rs.stepdown()
primary故障
申请条件
primary心跳检测不可达时间 超过electionTimeoutMillis 设定的值
自身可以访问多数节点(超过半数)
具有投票权和选举权:priority>0 && votes>0
PRIMARY 发现副本集中多数节点不可访问之后会降级为SECONDARY 节点,当副本集中最后一个primary几点降级后,副本集不再提供写服务,读取首选项设置为从库可读时,可以继续提供读服务
读写分离
读写分离是连接副本集指定读取首选项(Read Preference)的参数
参数 说明
primary 默认模式。只读主库
primaryPreferred 优先读主库,不可读时读从库
secondary 只读从库
secondaryPreferred 优先读从库,不可读时读主库
nearest 最近读
rs.slaveOk()允许从库执行查询,只有在可读的从节点操作才有意义(仲裁,隐藏等不可读节点无效),也只有在单独连接从库时生效,连接集群时还需要指定读取首选项
附录 —添加用户权限
在主节点创建账户
use master;
#数据库管理员账户
db.createUser(
{
user:“root”,
pwd:“root”,
roles:[
{role:“readWriteAnyDatabase”,db:“admin”},
{role:“dbAdminAnyDatabase”,db:“admin”},
{role:“userAdminAnyDatabase”,db:“admin”}
]
}
)
#集群管理员账户
db.createUser(
{
user:“suroot”,
pwd:“suroot”,
roles:[
{role:“clusterAdmin”,db:“admin”},
{role:“clusterManager”,db:“admin”},
{role:“clusterMonitor”,db:“admin”}
]
}
)
use testrs; #数据库不用事先创建
#指定库账户
db.createUser(
{
user:“test”,
pwd:“test”,
roles:[
{role:“readWrite”,db:“testrs”},
{role:“dbAdmin”,db:“testrs”},
{role:“userAdmin”,db:“testrs”}
]
}
)
关闭所有的mongo服务
mongod --shutdown -f /root/mongo/conf/mongod.conf
生成keyFile
keyFile的用途是作为所有mongod后台进程允许加入集群的凭证, 所有集群中的节点共用一个keyFile, 避免其他mongod非法加入集群
在一个节点生成keyFile,之后分发到节点机器
openssl rand -base64 756 > /root/mongo/conf/access.key #生成keyFile, keyFile的长度必须在6-1024个字符之间
#设置keyFile文件为400或600
chmod 400 /root/mongo/conf/access.key
#将keyFile复制到其他节点
scp /root/mongo/conf/access.key root@192.168.158.121:/root/mongo/conf/
scp /root/mongo/conf/access.key root@192.168.158.122:/root/mongo/conf/
特别说明一个BUG,chmod keyFile修改权限是因为mongo启动时会验证权限,如果keyFile的权限是
-rw-r–r-- 1 root root 1024 Apr 19 03:08 access.key
在启动时mongo的启动日志会报错
2019-04-19T03:14:02.372-0400 I ACCESS [main] permissions on /root/mongo/conf/access.key are too open
重新启动mongo
mongod -f /root/mongo/conf/mongod.conf
mongo
连入mongo后验证
#切换到集群管理员账户
db.auth(“suroot”,“suroot”)
#集群管理员权限才能执行
rs.status()
#切换到数据库管理员账户
db.auth(“root”,“root”)
db.system.users.find().pretty()
…
也可以在登陆时指定数据库和对应用户
mongo test --username test --password test