02-Mongo 副本集
副本集
A replica set in MongoDB is a group of
mongodprocesses that maintain the same data set. Replica sets provide redundancy and high availability, and are the basis for all production deployments.
- 一个副本集是一组mongo实例, 它们维护着相同的数据集。
- 副本集提供数据冗余和高可用, 是生产环境部署的基本环境。
- 只能解决数据安全和高可用, 不能解决高负载
副本集中的成员
- primary 主节点, 接受所有的写操作
- secondary 从结点,维护与主节点一致的数据副本, 可以承载读操作。
- arbiter 仲裁者, 在选举primary时参与投票, 自己不承载数据,也不会成为primary
Mongo中的副本集是一组mongo实例,它们维护着相同的数据集。一个副本集包含多个数据承载结点和一个可选的仲裁结点。在多个数据承载结点中,只有一个结点是primary结点, 其余都是secondary结点。 primary结点接受所有 write 操作。
在副本集中使用{w:'majority'}写注意策略时,只有一个primary有能力去确认写操作,虽然某些情况下其他mongod实例会短暂地任务自己也是primary。primary会记录所有对数据集的变更操作, 例如 oplog。 secondary 会复制primary的oplog并应用其中的操作到自己的数据集上。当primary不可用时,有资格成为primary的secondary结点会选举新的primary。
副本集的同步
- secondary异步地复制primary的oplog并将其操作应用到当前数据集
自动故障转移
- 当primary与副本集中共其他成员失去通信(默认10s)一段时间后, 一个有资格的secondary发起选举并提名自己作为primary。 集群会尝试完成新primary的选举并恢正常
- 在副本集没有完成选举时,无法执行写操作。在primary离线期间,如果配置为在secondary中读则副本集仍然可以提供读操作
- 在默认配置下,集群完成选举前的中间时间不会超过12s。 这其中包括标记primary不可用的时间以及发起选举并完成选举。
- 将 electionTimeoutMillis 修改地更小会导致更频繁的故障转移和选举,即使只是网络延迟。
读操作
read perference
- 副本集默认在primary上执行读操作。 但是可以手动指定 readPerference 为 secondary 将读操作发送到secondary结点
- 由于secondary是异步复制,这意味着读操作可能读取的数据不是primary中的最新数据
Multi-documnet transactions控制读操作必须使用 readPerference 为 primary. 给定事务中的所有操作必须路由到相同的结点。
数据可见性
副本集搭建
集群配置
# 在三台服务器上配置, 用相同的名称
vim /etc/mongod.conf
# 同一个副本集的名称要一致
replication:
replSetName: 'rs0'
初始化集群
mongosh test.mongo1.db
rs.initiate( {
: "rs0",
members: [
{ _id: 0, host: "test.mongo1.db:27017" }, #一定要使用域名或局域网IP
{ _id: 1, host: "test.mongo2.db:27017" },
{ _id: 2, host: "test.mongo3.db:27017" }
])
{ ok: 1 }
查看集群配置
rs.conf();
rs.status();#查看副本集状态
{
_id: 'rs0',
version: 1,
term: 0,
members: [
{
_id: 0,
host: 'test.mongo1.db:27017',
arbiterOnly: false,
buildIndexes: true,
hidden: false,
priority: 1,
tags: {},
secondaryDelaySecs: Long("0"),
votes: 1
},
{
_id: 1,
host: 'test.mongo2.db:27017',
arbiterOnly: false,
buildIndexes: true,
hidden: false,
priority: 1,
tags: {},
secondaryDelaySecs: Long("0"),
votes: 1
},
{
_id: 2,
host: 'test.mongo3.db:27017',
arbiterOnly: false,
buildIndexes: true,
hidden: false,
priority: 1,
tags: {},
secondaryDelaySecs: Long("0"),
votes: 1
}
],
protocolVersion: Long("1"),
writeConcernMajorityJournalDefault: true,
settings: {
chainingAllowed: true,
heartbeatIntervalMillis: 2000,
heartbeatTimeoutSecs: 10,
electionTimeoutMillis: 10000,
catchUpTimeoutMillis: -1,
catchUpTakeoverDelayMillis: 30000,
getLastErrorModes: {},
getLastErrorDefaults: { w: 1, wtimeout: 0 },
replicaSetId: ObjectId("65410a4fb993537e930c3cc2")
}
}
写入数据
在一个结点写入数据,在其他结点查询数据
db.movies.insertOne(
{
title: "人猿泰山",
genres: [ "大山", "卡档夫" ],
runtime: 121,
rated: "R",
year: 2018,
directors: [ "Yorgos Lanthimos" ],
cast: [ "Olivia Colman", "Emma Stone", "Rachel Weisz" ],
type: "movie"
}
)
db.movies.find( { title: "The Favourite" } )
在 secondary 结点上执行查询操作出错:
MongoServerError: not primary and secondaryOk=false - consider using db.getMongo().setReadPref() or readPreference in the connection string
需要在 seconda 结点上执行 db.getMongo().setReadPref('secondary')
db.getMongo().setReadPref('secondary')
灾备测试
- 停止 primary 结点, 其他结点自动选举为 primary
- 在新的 primary 上写入数据
- 启动停止的结点, 数据会同步到新的结点上
compass/springdata 使用
mongodb://test.mongo1.db:27017,test.mongo2.db:27017,test.mongo3.db:27017/{dbname}/?replicaSet={replicaName}&readPreference=secondary

浙公网安备 33010602011771号