MongoDB提供了两种复制部署方案:主从复制和副本集。两种方式共同点是只在一个主节点上进行写操作,然后写入的数据会异步的同步到所有的从节点上。但主从复制有明显的缺陷:当主节点出现故障停电或者死机等情况,整个MongoDB服务集群就不能正常工作了,需要人工的处理这种情况。而副本集是具有自动故障恢复功能的主从复制。所以一般都用副本集。
当副本集的总可投票数为偶数时,可能出现无法选举出主节的情况。2个节点组成副本集是不合理的,因为这样的副本集不具备故障切换能能力:
·当 SECONDARY节点挂掉,剩下一个 PRIMARY,此时副本集运行不会出现问题,但不具备副本集的功能了,相当于单实例 Mongodb服务
·当 PRIMARY节点挂掉,此时副本集只剩下一个 SECONDARY,它只有1票,不超过总节点数的半数,不会成功选举自己为 PRIMARY节点。会错误提示。
因此我们有两种方案,
一是设置 MONGODB集群的节点数量为奇数。
二是当Mongodb集的节点数量为偶数时,适当增加仲裁节点,增加集群的稳定性。
所以尝试部署副本集的可行方案是:3个数据节点或2个数据节点+1个仲裁节点
先在3台机器上都安装MongoDB
第一台机器:192.168.32.135
mkdir -p /data/replset/data1 #1号机器存放数据的目录
mkdir -p /data/replset/key #存放秘钥的目录
mkdir -p /data/replset/log #存放日志的目录
第二台机器:192.168.32.137
mkdir -p /data/replset/data2 #2号机器存放数据的目录
mkdir -p /data/replset/key #存放秘钥的目录
mkdir -p /data/replset/log #存放日志的目录
第三台机器:192.168.32.138
mkdir -p /data/replset/data3 #3号机器存放数据的目录
mkdir -p /data/replset/key #存放秘钥的目录
mkdir -p /data/replset/log #存放日志的目录
副本集认证的总体思路是用户名,密码和keyFile文件。KeyFile需要各个副本集服务启动时加载而且KeyFile文件的内容必须一致
KeyFile文件必须满足条件:
注意:秘钥是集群中服务器之间进行沟通使用的
第一台机器:
echo replsetkey> /data/replset/key/r1
chmod 400 /data/replset/key/r1
第二台机器:
echo replsetkey> /data/replset/key/r2
chmod 400 /data/replset/key/r2
第三台机器:
echo replsetkey> /data/replset/key/r3
chmod 400 /data/replset/key/r3
开启了KeyFile,隐含就开启了auth 所以不用在配置文件中配置authorization: enable了
vim /etc/mongod.conf
第一台机器:
第二台机器:
第三台机器:
./mongod --config /etc/mongod.conf
出现上面代表启动成功
启动三台MongoDB服务后,开始把他们初始化为副本集。在想要设置成primary(主节点)的机器上运行客户端mongo。例如第1台机器上:
6.1、启动客户端
./mongo
6.2、执行 rs.initiate()
说明初始化成功!
rs.conf()查看副本集配置,因为我的myadmin只付给了userAdminAnyDatabase权限。如果提示没有权限,则执行以下代码:
db.grantRolesToUser( "myadmin" , [ { role: "dbOwner", db: "admin" },{ "role": "clusterAdmin", "db": "admin" },
{ "role": "userAdminAnyDatabase", "db": "admin" },
{ "role": "dbAdminAnyDatabase", "db": "admin" },
{ role: "root", db: "admin" } ])
信息如下:
6.3、添加secondary节点
例如将第2台机器设为secondary节点
rs.add("192.168.32.137:27017");
如果还要添加更多的secondary节点,执行rs.add(“主机名/IP:端口”)即可
6.4、添加仲裁节点ARBITER
将第三台机器设为仲裁节点
rs.addArb("192.168.32.138:27017")
如果还要添加更多的arbiter节点,执行rs.addArb(“主机名/IP:端口”)即可
查看集群情况可以使用命令:rs.status()
1)首先向PRIMARY(主节点)写入一条数据
2)启动第二台机器的客户端,进入SECONDARY(副节点)
默认情况下SECONDARY节点不能读写,要设置slaveOK为true才行。集群中只能有一个Primary节点,只能在Primary写数据,不能在SECONDARY写数据
例如:
db.getMongo().setSlaveOk()或rs.slaveOk()
然后查看say集合
副本集还有个很重要的功能就是故障切换,把主节点关闭,看看副本点是否能接替主节点进行工作。
在第1台机器执行db.shutdownServer()
然后发现第2台机器 SECONDARY节点变成了PRIMARY节点:
rs.status()查看集群状态,发现第1台机器的状态是:
public class ReplSetTest {
public static void main(String[] args) {
//副本集
final List servers=new ArrayList();
servers.add(new ServerAddress("192.168.32.135", 27017));
servers.add(new ServerAddress("192.168.32.137", 27017));
servers.add(new ServerAddress("192.168.32.138", 27017));
//认证信息
String user="myTest"; // the user name
String db="test"; // the name of the database in which the user is defined
char[] password="123".toCharArray(); // the password as a character array
MongoCredential credential = MongoCredential.createCredential(user,db, password);
MongoClientSettings settings = MongoClientSettings.builder()
.credential(credential)
.applyToClusterSettings(new Block() {
public void apply(
com.mongodb.connection.ClusterSettings.Builder t) {
t.hosts(servers);// 副本集
}
}).build();
MongoClient mongoClient = MongoClients.create(settings);
MongoDatabase database = mongoClient.getDatabase("test");
MongoCollection collection = database.getCollection("book");
//插入数据
collection.insertOne(new Document("name","高数"));
collection.insertOne(new Document("name","MongoDB从入门到精通"));
MongoCursor iterator = collection.find().iterator();
while(iterator.hasNext()){
System.out.println(iterator.next().toJson());
}
}
}
1)不能使用service mongod start启动服务,否则报错
2)使用keyFile模式启动数据库服务,默认会启用--auth认证模式。一般需要先在单例模式下创建好用户,再使用--keyFile模式启动,认证后访问数据库。(否则没权限)
3)初始化还可以用这种方式:
rs.initiate(
{
_id : ,
members: [
{ _id : 0, host : "192.168.32.135:27017,priority:4" },
{ _id : 1, host : "192.168.32.137:27017,priority:2" },
{ _id : 2, host : "192.168.32.138:27017,arbiterOnly:true" }
]
}
)
4)新版本MongoDB客户端构造函数new MongoClient()已经不推荐使用了,改为MongoClients.create()