MongoDB的副本集(Replica Set)是一种用于提高数据库系统可用性、可靠性和数据冗余性的机制。副本集包含一组相互连接的MongoDB节点,其中包括一个主节点(Primary)和多个从节点(Secondary)。主节点处理所有的写入操作以及读取操作,而从节点则通过异步复制主节点上的操作来保持数据的一致性,从而作为数据的热备份。如果主节点发生故障,从节点之一可以通过选举过程升级为主节点,以保证服务的连续性。
MongoDB副本集通常由以下部分组成:
仲裁者(Arbiter)在MongoDB副本集中扮演着重要的角色,下面是仲裁者的作用
mongo1 |
mongo2 |
端口 |
角色 |
shared server1(Primary) |
shared server1(Primary) |
27017 |
主节点 |
shared server2(Secondary) |
shared server2(Secondary) |
27018 |
副本节点 |
shared server3(Secondary) |
shared server3(Secondary) |
27019 |
副本节点 |
shared server4(Arbiter) |
shared server4(Arbiter) |
27020 |
仲裁节点 |
下载适用于Linux系统的MongoDB安装包,并解压至指定路径。
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-5.0.2.tgz
tar -xzvf mongodb-linux-x86_64-rhel70-5.0.2.tgz -C /usr/local
cd /usr/local/
mv mongodb-linux-x86_64-rhel70-5.0.2/ /usr/local/mongodb
mkdir -p /usr/local/mongodb/replica_sets/myrs_27017/{log,data/db}
vim /usr/local/mongodb/replica_sets/myrs_27017/mongod.conf
systemLog:
destination: file
path: "/usr/local/mongodb/replica_sets/myrs_27017/log/mongod.log"
logAppend: true
storage:
dbPath: "/usr/local/mongodb/replica_sets/myrs_27017/data/db"
journal:
enabled: true
processManagement:
fork: true
pidFilePath: "/usr/local/mongodb/replica_sets/myrs_27017/log/mongod.pid"
net:
bindIp: localhost,10.0.1.10
port: 27017
replication:
replSetName: myrs
/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/replica_sets/myrs_27017/mongod.conf
about to fork child process, waiting until server is ready for connections.
forked process: 15214
child process started successfully, parent exiting
mkdir -p /usr/local/mongodb/replica_sets/myrs_{27018,27019,27020}/{log,data/db}
vim /usr/local/mongodb/replica_sets/myrs_27018/mongod.conf
systemLog:
destination: file
path: "/usr/local/mongodb/replica_sets/myrs_27018/log/mongod.log"
logAppend: true
storage:
dbPath: "/usr/local/mongodb/replica_sets/myrs_27018/data/db"
journal:
enabled: true
processManagement:
fork: true
pidFilePath: "/usr/local/mongodb/replica_sets/myrs_27018/log/mongod.pid"
net:
bindIp: localhost,10.0.1.10
port: 27018
replication:
replSetName: myrs
vim /usr/local/mongodb/replica_sets/myrs_27019/mongod.conf
systemLog:
destination: file
path: "/usr/local/mongodb/replica_sets/myrs_27019/log/mongod.log"
logAppend: true
storage:
dbPath: "/usr/local/mongodb/replica_sets/myrs_27019/data/db"
journal:
enabled: true
processManagement:
fork: true
pidFilePath: "/usr/local/mongodb/replica_sets/myrs_27019/log/mongod.pid"
net:
bindIp: localhost,10.0.1.10
port: 27019
replication:
replSetName: myrs
/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/replica_sets/myrs_27018/mongod.conf
/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/replica_sets/myrs_27019/mongod.conf
vim /usr/local/mongodb/replica_sets/myrs_27020/mongod.conf
systemLog:
destination: file
path: "/usr/local/mongodb/replica_sets/myrs_27020/log/mongod.log"
logAppend: true
storage:
dbPath: "/usr/local/mongodb/replica_sets/myrs_27020/data/db"
journal:
enabled: true
processManagement:
fork: true
pidFilePath: "/usr/local/mongodb/replica_sets/myrs_27020/log/mongod.pid"
net:
bindIp: localhost,10.0.1.10
port: 27020
replication:
replSetName: myrs
/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/replica_sets/myrs_27020/mongod.conf
vim /etc/profile
export PATH=/usr/local/mongodb/bin/:$PATH
source /etc/profile
which mongo
/usr/local/mongodb/bin/mongo
mongo --host 10.0.1.10 --port 27017
> rs.initiate()
myrs:PRIMARY> rs.conf()
myrs:PRIMARY> rs.add("10.0.1.10:27018")
myrs:PRIMARY> rs.add("10.0.1.10:27019")
myrs:PRIMARY> rs.addArb("10.0.1.10:27020")
遇到问题,rs.addArb无响应解决办法:
db.adminCommand({
"setDefaultRWConcern" : 1,
"defaultWriteConcern" : {
"w" : 2
}
})
myrs:PRIMARY> rs.conf()
{
"_id" : "myrs",
"version" : 6,
"term" : 2,
"members" : [
{
"_id" : 0,
"host" : "10.0.1.10:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"secondaryDelaySecs" : NumberLong(0),
"votes" : 1
},
{
"_id" : 1,
"host" : "10.0.1.10:27018",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"secondaryDelaySecs" : NumberLong(0),
"votes" : 1
},
{
"_id" : 2,
"host" : "10.0.1.10:27019",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"secondaryDelaySecs" : NumberLong(0),
"votes" : 1
},
{
"_id" : 3,
"host" : "10.0.1.10:27020",
"arbiterOnly" : true,
"buildIndexes" : true,
"hidden" : false,
"priority" : 0,
"tags" : {
},
"secondaryDelaySecs" : NumberLong(0),
"votes" : 1
}
]
_id
:0,成员的唯一标识符。host
:10.0.1.10:27017
,表示该成员的主机地址和端口。arbiterOnly
:false
,表示这不是一个仲裁节点。priority
:1,优先级为1,意味着它可以成为主节点。votes
:1,投票权重为1,参与选举投票。确保副本集已经正确配置并运行。可以通过以下命令查看副本集的配置:
myrs:PRIMARY> rs.conf()
插入数据在主节点上插入一些测试数据,以确保数据能够正确地写入并同步到从节点。
myrs:PRIMARY> use testdb;
myrs:PRIMARY> db.test.insertOne({ name: "John Doe", age: 30 });
{
"acknowledged" : true,
"insertedId" : ObjectId("66d57a427713464146c2cca9")
}
在主节点上查询刚刚插入的数据,确保数据已经成功插入。
myrs:PRIMARY> db.test.find();
{ "_id" : ObjectId("66d57a427713464146c2cca9"), "name" : "John Doe", "age" : 30 }
数据插入后,可能需要几秒钟的时间才能完全同步到从节点。可以使用 rs.status()
查看同步进度。
myrs:PRIMARY> rs.status()
查看 health
字段,确保从节点的状态为 1
。
连接到从节点,查询刚刚插入的数据,确保数据已经成功同步。
设置从节点有读取权限
myrs:SECONDARY> rs.secondaryOk()
设置从节点关闭读取权限
myrs:SECONDARY> rs.secondaryOk(false)
myrs:SECONDARY> use testdb;
myrs:SECONDARY> db.test.find();
{ "_id" : ObjectId("66d57a427713464146c2cca9"), "name" : "John Doe", "age" : 30 }
如果数据已经出现在从节点上,说明同步操作成功。
在主节点上更新刚刚插入的数据,再次验证同步操作。
myrs:PRIMARY> db.test.updateOne({ name: "John Doe" }, { $set: { age: 31 } });
验证更新同步在从节点上查询更新后的数据,确保数据已经同步。
myrs:SECONDARY> db.test.find();
{ "_id" : ObjectId("66d57a427713464146c2cca9"), "name" : "John Doe", "age" : 31 }
删除数据在主节点上删除刚刚插入的数据,再次验证同步操作。
myrs:PRIMARY> db.test.deleteOne({ name: "John Doe" });
验证删除同步在从节点上查询删除后的数据,确保数据已经同步删除。
myrs:SECONDARY> db.test.find();
mongo --host 10.0.1.10 --port 27020
myrs:ARBITER> rs.secondaryOk()
myrs:ARBITER> show dbs
uncaught exception: Error: listDatabases failed:{
"topologyVersion" : {
"processId" : ObjectId("66d563aefe48eda115ba75a8"),
"counter" : NumberLong(1)
},
"ok" : 0,
"errmsg" : "node is not in primary or recovering state",
"code" : 13436,
"codeName" : "NotPrimaryOrSecondary"
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs/<@src/mongo/shell/mongo.js:145:19
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:97:12
shellHelper.show@src/mongo/shell/utils.js:956:13
shellHelper@src/mongo/shell/utils.js:838:15
@(shellhelp2):1:1
MongoDB 副本集中的主节点选举规则是为了确保在一个分布式环境中选择一个合适的节点来承担主节点的角色。主节点负责处理所有的写操作,并将数据同步到从节点。以下是一些主要的选举规则和流程:
故障检测:
心跳机制:
选举开始:
选举资格:
priority
)、投票权重(votes
)和其他配置参数。优先级(Priority):
priority
),默认为1。优先级较高的节点更有可能成为主节点。选举顺序:
投票机制:
votes
),默认为1。节点需要获得大多数投票才能成为主节点。arbiterOnly
)不存储数据,但参与投票。仲裁节点的投票权重为1。多数票原则:
参考链接:Cluster-to-Cluster Sync - MongoDB Cluster-to-Cluster Sync v1.8
Cluster-to-Cluster Sync 通过 mongosync
实用程序提供 MongoDB 集群之间的持续数据同步或一次性数据迁移。
mongosync
可以在两个集群之间持续同步数据,帮助您创建反映生产环境的专用分析、开发或测试集群。
同步后的集群还能满足审计和数据驻留合规性的局部性要求。除了连续的数据同步外,mongosync
还可以用于集群间的一次性数据迁移。
wget https://github.com/alibaba/MongoShake/releases/download/release-v2.8.4-20230425/mongo-shake-v2.8.4.tgz
tar -xzvf mongo-shake-v2.8.4.tgz -C /usr/local
cd /usr/local/
mv mongo-shake-v2.8.4/ mongoshake
vim /usr/local/mongoshake/collector.conf
mongo_urls = mongodb://10.0.1.10:27017,10.0.1.10:27018,10.0.1.10:27019,10.0.1.10:27020
tunnel.address = mongodb://10.0.1.20:27017,10.0.1.20:27018,10.0.1.20:27019,10.0.1.20:27020
sync_mode = all
incr_sync.mongo_fetch_method = oplog
./collector.linux -conf=collector.conf -verbose 1
在10.0.1.10发送端插入数据
mongo --host 10.0.1.10 --port 27017
myrs:PRIMARY> use testdb;
myrs:PRIMARY> db.test.insertOne({ name: "ke li", age: 22 });
myrs:PRIMARY> db.test.find();
{ "_id" : ObjectId("66d6c61f2f0fd77307a32d80"), "name" : "ke li", "age" : 22 }
在10.0.1.20可以查看到数据
mongo --host 10.0.1.20 --port 27017
myrs:PRIMARY> use testdb;
myrs:PRIMARY> db.test.find();
{ "_id" : ObjectId("66d6c61f2f0fd77307a32d80"), "name" : "ke li", "age" : 22 }
验证成功,实现了单向实时同步功能。
通过MongoShake实现MongoDB实例的单向同步_云数据库 MongoDB 版(MongoDB)-阿里云帮助中心 (aliyun.com)
Mongo-shake-阿里云开发者社区 (aliyun.com)
MongoShake最佳实践-阿里云开发者社区 (aliyun.com)