复制集(replica set)
复制集是一组mongodb的进程维护同样的数据集,提供冗余与高可用性。最小的复制集由3台服务器(或者3个实例)组成,最多1个primary和2个secondary实例,其中只有primary允许读写,secondary只读。secondary和primary的数据完全一致,它们之间通过primary实例的oplog异步(asynchronous)方式同步数据。


oplog(operations log)是专门的capped collection,保存所有数据库相关修改的回滚记录,secondary成员通过异步的方式拷贝和执行这些操作。
当primary不可用时,复制集发起投票(elections),选择1台secondary做为primary,请注意priority这个参数,priority为0的secondary不能成为primary,不能触发投票。
Oplog Size
在Unix和Windows系统中, 如果存储引擎使用的是WiredTiger,将占用剩余使用空间的5%。

# 生产环境部署
kvm-70-101 10.0.70.101 # primary
kvm-70-102 10.0.70.102 # secondary
kvm-70-103 10.0.70.103 # secondary
openssl rand -base64 756 > mongodb_product_key
chmod 400 mongodb_product_key
chown mongod mongodb_product_key
security:
keyFile: /etc/mongodb_product_key
replication:
replSetName: myapp
rs.initiate( {
_id : 'myapp',
members: [ { _id : 0, host : 'kvm-70-101:27017' }, { _id : 1, host : 'kvm-70-102:27017' }, { _id : 2, host : 'kvm-70-103:27017' } ]
})
{
"info" : "try querying local.system.replset to see current configuration",
"ok" : 0,
"errmsg" : "already initialized",
"code" : 23,
"codeName" : "AlreadyInitialized"
}
use admin
db.createUser(
{
user: 'admin',
pwd: '@admin',
roles: [ { role: 'root', db: 'admin' } ]
}
);
use app
db.createUser(
{
user: 'app',
pwd: '@app',
roles: [ { role: 'dbOwner', db: 'app' } ]
}
);
db.auth('admin', '@admin')
rs.add('kvm-70-104:27017')
rs.add('kvm-70-104:27017')
rs.conf()
{
"_id" : "myapp",
"version" : 3,
"protocolVersion" : NumberLong(1),
"members" : [
{
"_id" : 0,
"host" : "kvm-70-101:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 1,
"host" : "kvm-70-102:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 2,
"host" : kvm-70-103: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" : 2000,
"getLastErrorModes" : {
},
"getLastErrorDefaults" : {
"w" : 1,
"wtimeout" : 0
},
"replicaSetId" : ObjectId("59248e52d45510744805fb78")
}
}
# 查看状态
rs.status()
{
"set" : "myapp",
"date" : ISODate("2017-05-23T20:37:08.946Z"),
"myState" : 1,
"term" : NumberLong(1),
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1495571827, 1),
"t" : NumberLong(1)
},
"appliedOpTime" : {
"ts" : Timestamp(1495571827, 1),
"t" : NumberLong(1)
},
"durableOpTime" : {
"ts" : Timestamp(1495571827, 1),
"t" : NumberLong(1)
}
},
"members" : [
{
"_id" : 0,
"name" : "kvm-70-101:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 4968,
"optime" : {
"ts" : Timestamp(1495571827, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2017-05-23T20:37:07Z"),
"electionTime" : Timestamp(1495567955, 2),
"electionDate" : ISODate("2017-05-23T19:32:35Z"),
"configVersion" : 3,
"self" : true
},
{
"_id" : 1,
"name" : "kvm-70-102:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 77,
"optime" : {
"ts" : Timestamp(1495571827, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1495571827, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2017-05-23T20:37:07Z"),
"optimeDurableDate" : ISODate("2017-05-23T20:37:07Z"),
"lastHeartbeat" : ISODate("2017-05-23T20:37:07.702Z"),
"lastHeartbeatRecv" : ISODate("2017-05-23T20:37:06.951Z"),
"pingMs" : NumberLong(0),
"syncingTo" : "10.0.70.103:27017",
"configVersion" : 3
},
{
"_id" : 2,
"name" : "kvm-70-103:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 77,
"optime" : {
"ts" : Timestamp(1495571827, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1495571827, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2017-05-23T20:37:07Z"),
"optimeDurableDate" : ISODate("2017-05-23T20:37:07Z"),
"lastHeartbeat" : ISODate("2017-05-23T20:37:07.708Z"),
"lastHeartbeatRecv" : ISODate("2017-05-23T20:37:07.733Z"),
"pingMs" : NumberLong(0),
"syncingTo" : "10.0.70.101:27017",
"configVersion" : 3
}
],
"ok" : 1
}
rs.slaveOk()
use app
db.auth('app', '@app')
db.test.insert({'hello': 'world'})
rs0:SECONDARY> db.test.find().pretty();
{ "_id" : ObjectId("5ad6c7e574a09792011db5ee"), "hello" : "world" }
rs.stepDown()
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类