MongoDB副本集实现故障自动切换至少需要以下配置为:
1.一个主节点,两个从节点
2.一个主节点,一个从节点一个仲裁节点。
如果只有一主一从节点,故障时无法选举出主节点从而实现切换。
在三台服务器上安装MongoDB,同时在主节点数据库上提前创建好有副本集权限的用户。
当然你也可以选择安装在同一台服务器上(除了测试用,不然意义不大)。
安装部分请自行搜索网上资料,在此不再赘述。
修改三个Mongo配置文件,都加入以下配置
第一个参数是指定副本集
第二个参数是使用key进行安全认证
replSet=test_resplset
keyFile=/usr/local/mongodb/conf/mongodb_key
如果配置中有auth=on
项,请删除,否则会造成节点没有权限连接。副本集使用key文件进行安全认证。
> openssl rand -base64 102 /usr/local/mongodb/conf/mongodb_key
生成key文件
> chmod 600 /usr/local/mongodb/conf/mongodb_key
赋600权限
正常启动三个Mongo服务即可
> /usr/local/mongodb/bin/mongod -f /usr/local/mongodb/conf/mongodb.conf
然后连接一台你想使其成为主节点的数据库。
连接主节点后,输入:
> config = {
"_id" : "test_resplset",
"members" : [
{
"_id" : 0,
"host" : "192.168.1.123:27020",
"priority" : 99
},
{
"_id" : 1,
"host" : "192.168.1.124:27021"
},
{
"_id" : 2,
"host" : "192.168.1.125:27022",
"arbiterOnly" : true
}
] }
arbiterOnly: true
指这个节点为仲裁节点。
这里无论你的三个服务是否在同一个服务器上,都不要使用127.0.0.1
地址,否则稍后连接数据库的时候会连接不上(域名我没测试过,各位可以自己尝试)。
> rs.initiate(config)
初始化集群。这两步只需要在主节点上操作一次即可。
出现{"ok":1}
代表配置成功。
如果此处报没有权限认证的错误,请先使用有副本集权限的用户进行权限认证。
> use admin
> db.auth("user","pwd")
如果提示本节点不是主节点,请关闭主节点数据库,注释掉指定副本集参数后单机启动,然后进行操作。操作完成后重新以副本集启动。
> rs.status() // 查看集群状态
{
"set" : "test_resplset",
"date" : ISODate("2019-04-19T08:39:05.420Z"),
"myState" : 1,
"term" : NumberLong(1),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1555663135, 1),
"t" : NumberLong(1)
},
"readConcernMajorityOpTime" : {
"ts" : Timestamp(1555663135, 1),
"t" : NumberLong(1)
},
"appliedOpTime" : {
"ts" : Timestamp(1555663135, 1),
"t" : NumberLong(1)
},
"durableOpTime" : {
"ts" : Timestamp(1555663135, 1),
"t" : NumberLong(1)
}
},
"lastStableCheckpointTimestamp" : Timestamp(1555663085, 1),
"members" : [
{
"_id" : 0,
"name" : "192.168.1.123:27020",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 795,
"optime" : {
"ts" : Timestamp(1555663135, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2019-04-19T08:38:55Z"),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "could not find member to sync from",
"electionTime" : Timestamp(1555663083, 1),
"electionDate" : ISODate("2019-04-19T08:38:03Z"),
"configVersion" : 1,
"self" : true,
"lastHeartbeatMessage" : ""
},
{
"_id" : 1,
"name" : "192.168.1.124:27021",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 71,
"optime" : {
"ts" : Timestamp(1555663135, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1555663135, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2019-04-19T08:38:55Z"),
"optimeDurableDate" : ISODate("2019-04-19T08:38:55Z"),
"lastHeartbeat" : ISODate("2019-04-19T08:39:03.693Z"),
"lastHeartbeatRecv" : ISODate("2019-04-19T08:39:04.714Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "192.168.1.123:27020",
"syncSourceHost" : "192.168.1.123:27020",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 1
},
{
"_id" : 2,
"name" : "192.168.1.125:27022",
"health" : 1,
"state" : 7,
"stateStr" : "ARBITER",
"uptime" : 71,
"lastHeartbeat" : ISODate("2019-04-19T08:39:03.691Z"),
"lastHeartbeatRecv" : ISODate("2019-04-19T08:39:03.615Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"configVersion" : 1
}
],
"ok" : 1,
"operationTime" : Timestamp(1555663135, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1555663135, 1),
"signature" : {
"hash" : BinData(0,"KMcQWa4w+xlc02Atf6a/uv6DH9I="),
"keyId" : NumberLong("6681522073669468161")
}
}
}
可以看到一个主节点,一个仲裁节点,一个从节点。
人懒,此处就简单使用单元测试做个例子吧。上代码:
@Data
@Document(collection = "test")
class Author {
private String name;
}
@Test
public void testReadMongoReplSet() {
MongoClientURI mongoClientURI = new MongoClientURI("mongodb://user:[email protected]:27020,192.168.1.124:27021/test_resplset?replicaSet=test_resplset&authSource=test_resplset&readPreference=secondaryPreferred&safe=true&authMechanism=SCRAM-SHA-1&maxPoolSize=500&minPoolSize=10");
SimpleMongoDbFactory mongoDbFactory = new SimpleMongoDbFactory(mongoClientURI);
MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory);
System.out.println(mongoTemplate.find(new Query(),Author.class));
try {
mongoDbFactory.destroy();
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void testWriteMongoReplSet() {
MongoClientURI mongoClientURI = new MongoClientURI("mongodb://user:[email protected]:27020,192.168.1.124:27021/test_resplset?replicaSet=test_resplset&authSource=test_resplset&readPreference=secondaryPreferred&safe=true&authMechanism=SCRAM-SHA-1&maxPoolSize=500&minPoolSize=10");
SimpleMongoDbFactory mongoDbFactory = new SimpleMongoDbFactory(mongoClientURI);
MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory);
Author a= new Author();
a.setName("testWrite");
mongoTemplate.insert(a);
try {
mongoDbFactory.destroy();
} catch (Exception e) {
e.printStackTrace();
}
}
mongodb://user:[email protected]:27020,192.168.1.124:27021/test_resplset?replicaSet=test_resplset&authSource=test_resplset&readPreference=secondaryPreferred&safe=true&authMechanism=SCRAM-SHA-1&maxPoolSize=500&minPoolSize=10
我们来看下这链接地址。
首先整体格式应该满足:
mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]
username:password
用户名密码没啥好说的。192.168.1.123:27020,192.168.1.124:27021
这一段填的是主从节点的地址,仲裁节点不需要填写。/test_resplset
这里是指的数据库名replicaSet=test_resplset
指定副本集(这里是因为我数据库名和副本集名建的一样,实际并不一样,自己注意)authSource=test_resplset
认证的数据库readPreference=secondaryPreferred
读走从节点safe=true
在执行更新操作之后,驱动都会发送getLastError命令来确保更新成功执行成功时,会在控制台打印相应日志,能够看到读写走的哪个服务。
192.168.1.123:27020
为主节点,写服务走它。
192.168.1.124:27021
为从节点,读服务走它。
192.168.1.125:27022
为仲裁节点,连接时不需要写上。
如果是Springboot 直接使用@Autowired
注入MongoTemplate
,同时在配置文件中加入那串地址就行,没上面这么麻烦。
本文内容为本人学习MongoDB副本集过程中的简单知识总结,以防止自己遗忘。如有错误,欢迎批评指正。