搭建MongoDB集群
搭建一个简单的MongoDB副本集的过程
准备过程
服务器信息
三台服务器信息如下:
- 系统版本: CentOS 7 7.6.1810
- IP和主机信息:
- mongodb_1 : 192.168.187.209
- mongodb_2 : 192.168.187.210
- mongodb_3 : 192.168.187.211
- 安装MongoDB版本: 4.2
设置主机名
设置主机名, 根据预先的规划,分别登陆机器设置主机名字。
1 | sudo hostnamectl set-hostname mongodb_1 |
设置主机名,添加如下信息到三台机器的/etc/hosts中。
1 | sudo cat >> /etc/hosts << EOF |
SeLinux配置
如果要使用自定义的mongodb数据或日志路径,建议关闭SELinux。
在配置文件/etc/selinux/config中,将SELINUX=enforcing改为SELINUX=disabled
如果确定需要启动SeLinux, 并且需要使用自定义的数据路径,则可以参考官网设置。install-mongodb-on-red-hat/#configure-selinux
安装MongoDB
在三台服务器上分别安装MongoDB 4.2。完全4.2的安装步骤可参见官网Install MongoDB Community Edition on Red Hat or CentOS
三台服务器上,添加mongodb的yum源
1 | sudo cat >> /etc/yum.repos.d/mongodb.repo << \EOF |
三台服务器上, 安装MongoDB
1 | sudo yum install mongodb-org |
三台服务器上,开启防火墙,允许27017端口访问
1 | sudo firewall-cmd --add-service=mongodb --permanent |
三台服务器上,在/opt目录下创建mongodb相关的目录
1 | sudo mkdir -p /opt/mongodb/data |
三台服务器上,修改mongodb配置文件/etc/mongod.conf, 修改数据路径,日志路径和服务绑定IP等信息。
- 数据路径: 设置
storage.dbPath为/opt/mongodb/data - 日志路径: 设置
systemLog.path为/opt/mongodb/log/mongod.log - 服务绑定IP: 设置
net.bindIp为各个机器的内网地址,192.168.187.209,192.168.187.210和192.168.187.211 - 设置副本集名称: 设置
replication.replSetName为replicasetTest0,replicasetTest0是副本集名称,可以根据实际进行修改,同一副本集所有实例,name需要一致。 - 认证信息暂时先不设置,配置完集群设置的时候一起设置。
以服务器mongodb_1为例,此处的bindIp就应该是192.168.187.209, 对应的修改项如下。
设置之前先备份,永远是一个好习惯sudo cp /etc/mongod.conf /etc/mongod.conf.bak
1 | # where to write logging data. |
三台服务器上,启动mongodb服务。
1 | sudo systemctl enable mongod |
配置Replicaset
建立集群
登录任意一台服务器的mongo, 执行如下命令配置副本集。
1 | config = { _id:"replicasetTest0", members:[{_id:0,host:"192.168.187.209:27017" },{_id:1,host:"192.168.187.210:27017"},{_id:2,host:"192.168.187.211:27017"}]} |
执行结果:
1 | $ mongo |
协商阶段,提示符会变成副本集名字:SECONDARY,协商结束后,Primary的机器的提示符会变成副本集名字:SECONDARY。在我们的例子中就是replicasetTest0:SECONDARY和replicasetTest0:PRIMARY。
可以使用rs.status()来查看哪个服务器是PRIMARY,哪些服务器是SECONDARY。
创建root用户
在启动认证之前,需要先创建登录用户。
在PRIMARY节点上,执行mongo登录节点, 执行如下命令创建root用户。
1 | $ use admin |
执行结果如下:
1 | replicasetTest0:PRIMARY> use admin |
生成authKey
authKey用于实例认证,用于主从或者副本集直接验证,同副本集的文件内容需要一致
在mongodb_1上生成keyFile.
1 | sudo mkdir -p /etc/mongod/keyFiles/ |
在mongodb_2和mongodb_3上创建对应的目录和文件,将mongodb_1生成的key拷贝到mongodb_2和mongodb_3上。
1 | sudo mkdir -p /etc/mongod/keyFiles/ |
启用集群服务器的认证功能
三台服务器中启用认证功能。在/etc/mongod.conf中设置keyFile和authorization。
- 开启认证: 设置
security.authorization为enabled,启动登录认证。 - 配置认证key文件,设置
security.keyFile为上个步骤设置的文件/etc/mongod/keyFiles/mongo-key.
1 | security: |
配置过后,sudo systemctl restart mongod重启三台服务器。
验证是否启用了账号登录。
1 | $ mongo |
数据测试
此时,集群状态:mongodb_1为PRIMARY,mongodb_2和mongodb_3为SECONDARY。
登录Primary数据库,插入如下数据
执行mongo mongodb://my_root:mypassword@mongodb_1:27017登录Primary数据库。1
2
3
4
5
6
7use replicatestdata
db.createCollection("replicatestCollection01")
db.replicatestCollection01.insertMany([
{name: "test_record_one", description: "testing replica set", record: 1},
{name: "test_record_two", description: "testing replica set", record: 2},
{name: "test_record_three", description: "testing replica set", record: 3}
])在
mongodb_2上查看数据
执行mongo mongodb://my_root:mypassword@mongodb_2:27017登录mongodb_2数据库。1
2
3
4
5
6
7
8replicasetTest0:SECONDARY> db.getMongo().setSecondaryOk();
replicasetTest0:SECONDARY> use replicatestdata
switched to db replicatestdata
replicasetTest0:SECONDARY> db.replicatestCollection01.find()
{ "_id" : ObjectId("60ec094a7f37fee5e1bc1980"), "name" : "test_record_one", "description" : "testing replica set", "record" : 1 }
{ "_id" : ObjectId("60ec094a7f37fee5e1bc1981"), "name" : "test_record_two", "description" : "testing replica set", "record" : 2 }
{ "_id" : ObjectId("60ec094a7f37fee5e1bc1982"), "name" : "test_record_three", "description" : "testing replica set", "record" : 3 }
replicasetTest0:SECONDARY>在
mongodb_3上查看数据
执行mongo mongodb://my_root:mypassword@mongodb_3:27017登录mongodb_3数据库。1
2
3
4
5
6
7
8replicasetTest0:SECONDARY> db.getMongo().setSecondaryOk();
replicasetTest0:SECONDARY> use replicatestdata
switched to db replicatestdata
replicasetTest0:SECONDARY> db.replicatestCollection01.find()
{ "_id" : ObjectId("60ec094a7f37fee5e1bc1980"), "name" : "test_record_one", "description" : "testing replica set", "record" : 1 }
{ "_id" : ObjectId("60ec094a7f37fee5e1bc1982"), "name" : "test_record_three", "description" : "testing replica set", "record" : 3 }
{ "_id" : ObjectId("60ec094a7f37fee5e1bc1981"), "name" : "test_record_two", "description" : "testing replica set", "record" : 2 }
replicasetTest0:SECONDARY>
可以看到在PRIMARY mongodb_1中的数据,被复制到了mongodb_2和mongodb_3中。
一些Tips
启动mongod,报 ExecStart=/usr/bin/mongod $OPTIONS (code=exited, status=1/FAILURE)
stauts=1, 一般是文件权限问题,除了常规的用户组权限以外,如果CentOS开启了SELinux,注意还需要进行SELinux权限设置。参见官网文档install-mongodb-on-red-hat/#configure-selinux
集群配置
集群配置中,可以通过priority设置节点的优先级,还可以通过votes字段来设置节点是否加入投票。
例子:
1 | config = { _id:"rs", members:[{_id:0,host:"192.168.83.131:27017", priority : 100, votes: 1 },{_id:1,host:"192.168.83.33:27017", priority : 0, votes: 0}]} |
SECONDARY上开启查询
默认情况下,不能直接使用mongo命令在SECONDARY的节点上进行查询。如果要查询,需要先执行db.getMongo().setSecondaryOk();打开查询功能,然后再查询。
集群命令
rs.status(): 查看集群状态rs.conf(): 查看集群配置rs.add(): 添加集群节点rs.initiate(cfg): 使用配置信息初始化集群- cfg例子:
config = { _id:"rs", members:[{_id:0,host:"192.168.83.131:27017", priority : 100, votes: 1 },{_id:1,host:"192.168.83.33:27017", priority : 0, votes: 0}]}
- cfg例子:
rs.reconfig(cfg): 指定配置信息重置副本集;指定第二个参数{force:true},来强制更新- 例子: 剔除mongodb_3的节点,重置为两个节点:
rs.reconfig({ _id:"replicasetTest0", members:[{_id:0,host:"192.168.187.209:27017" },{_id:1,host:"192.168.187.210:27017"}]})
- 例子: 剔除mongodb_3的节点,重置为两个节点:
rs.add(membercfgobj): 使用指定配置,给副本集添加新成员- 例子: 重新添加
mongodb_3节点。rs.add( { host: "192.168.187.211:27017", priority: 1, votes: 1 } )
- 例子: 重新添加
rs.remove(hostportstr): 从副本集删除指定节点- 例子: 删除
mongodb_3节点。rs.remove("192.168.187.211:27017")
- 例子: 删除
rs.printReplicationInfo(): 查看操作日志以及日志时间rs.printSecondaryReplicationInfo(): 查看各个SECONDARY节点和PRIMARY之间的延迟情况