数据库系列之MongoDB主从复制集群环境

MongoDB集群环境有3种模式:主从复制、副本集和分片,本文详细介绍主从复制模式的部署和配置,并进行测试验证。

数据库系列之MongoDB主从复制集群环境
数据库系列之MongoDB副本集集群环境
数据库系列之MongoDB分片集群环境


1、MongoDB基本概念
1.1 MongoDB特性

MongoDB是一个可扩展的高性能、开源、模式自由,面向文档的数据库。它使用C++编写,主要包含以下特点:

  • 面向集合的存储:适合存储对象及JSON形式的数据
  • 动态查询:Mongo支持丰富的查询方式,查询指令使用JSON形式的标记,可轻易查询文档中内嵌的对象及数组
  • 完整的索引支持:包括文档内嵌对象及数组。Mongo 的查询优化器会分析查询表达式,并生成一个高效的查询计划
  • 查询监视:Mongo包含一个监控工具用于分析数据库操作性能
  • 复制及自动故障转移:Mongo 数据库支持服务器之间的数据复制,支持主-从模式及服务器之间的相互复制。复制的主要目的是提供冗余及自动故障转移
  • 高效的传统存储方式:支持二进制数据及大型对象(如照片或图片)
  • 自动分片以支持云级别的伸缩性:自动分片功能支持水平的数据库集群,可动态添加额外的机器
1.2 MongoDB集群架构

MongoDB集群环境有3中模式:主从复制、副本集和分片。

1)主从复制

主从复制模式,可用于备份、故障恢复和读扩展,最简单的设置是建立一个主节点和一个或多个从节点,结构图如下:

在这里插入图片描述

配置主从复制需要注意以下几点:

  • 在数据库集群中需明确知道谁是主服务器,主服务器只有一台
  • 从服务器要知道自己的数据源,也就是对应的主服务是谁
  • -master用来确定主服务器,-slave和-source来控制从服务器

2)副本集

副本集有点类似主从复制,不过跟真正的主从复制还是有两点区别的:

  • 该集群没有特定的主数据库
  • 如果哪个主数据库宕机了,集群中就会推选出一个从属数据库作为主数据库顶上,这就具备了自动故障恢复功能

结构图如下所示:

在这里插入图片描述

  • 第一张图表明A是活跃的B和C是用于备份的
  • 第二张图当A出现了故障,这时候集群根据权重算法推选出B为活跃的数据库
  • 第三张图当A恢复后他自动又会变为备份数据库

3)分片Sharding

分片技术,跟关系数据库的表分区类似,当数据量达到T级别的时候,服务器的磁盘和内存压力比较大,或者单个MongoDB服务器已经不能满足大量的插入操作,来针对这样的场景可以使用MongoDB提供的分片技术。当然分片除了解决空间不足的问题之外,还可以极大的提升的查询速度。

MongoDB采用将集合进行拆分,然后将拆分的数据均摊到几个片上, 结构如下图:

在这里插入图片描述

从图中可以看到有四个组件:mongos、configure server、shard、replica set:

  • mongos:数据库集群请求的入口,所有的请求都通过mongos进行协调,不需要在应用程序添加路由选择器,mongos自己就是一个请求分发中心,它负责把对应的数据请求请求转发到对应的shard服务器上。在生产环境通常有多mongos作为请求的入口,防止其中一个挂掉所有的mongodb请求都没有办法操作。
  • config server:配置服务器,存储所有数据库元信息(路由、分片)的配置。由于mongos本身没有物理存储分片服务器和数据路由信息,只是缓存在内存里,配置服务器则实际存储这些数据。mongos第一次启动或者关掉重启就会从config server加载配置信息,以后如果配置服务器信息变化会通知到所有的mongos更新自己的状态,这样mongos 就能继续准确路由。在生产环境通常有多个 config server 配置服务器,因为它存储了分片路由的元数据。当config servers replica sets的主服务丢失且无法选出一个primary,cluster的数据会变成只读。Shards中的数据还可以读写,但是不能出现chunk migration和chunk splits。如果所有config servers不可访问,cluster则不可操作。
  • shard:分片,保存具体的存储信息,分片的设置可以减少数据集中在一台机器的压力,减少硬盘的读写、网络的IO、CPU和内存的瓶颈。在MongoDB集群中只要设置好了分片规则,通过 mongos操作数据库就能自动把对应的数据操作请求转发到对应的分片机器上。在生产环境中分片的片键规则会影响到数据的均衡分布。
  • replica set:分片如果没有replica set是个不完整架构,假设其中的一个分片挂掉这部分数据就丢失了,所以在高可用性的分片架构还需要对于每一个分片构建replica set副本集以保证分片的可靠性。生产环境通常是2个副本+1个仲裁。
2、主从复制
2.1 配置主从服务器

1)解压安装文件到指定目录

[root@tango-centos01 src-install]# tar -xzvf mongodb-linux-x86_64-rhel70-3.6.3.tgz -C /usr/local/mongodb

2)创建数据文件路径

将数据文件和日志文件放在data目录下,并创建数据文件目录和日志文件目录

[root@tango-centos01 local]# cd mongodb
[root@tango-centos01 mongodb]# ls
mongodb-linux-x86_64-rhel70-3.6.3
[root@tango-centos01 mongodb]# mkdir data
[root@tango-centos01 mongodb]# mkdir logs
[root@tango-centos01 mongodb]# ls
data  logs  mongodb-linux-x86_64-rhel70-3.6.3

3)配置Master服务器

[root@tango-centos01 config]# vi master.conf
#MongoDB config - 2018.05.15

#config database path
dbpath = /usr/local/mongodb/data

#config log path
logpath = /usr/local/mongodb/logs/mongodb.log

#config port
port = 27017
bind_ip = 192.168.112.101

#config fork
fork = true

#master server
master = true

4)从主服务器拷贝介质到从服务器

[root@tango-centos01 local]# scp -r mongodb 192.168.112.102:/usr/local/
[root@tango-centos01 local]# scp -r mongodb 192.168.112.103:/usr/local/

5)配置Slave服务器

  • 节点2
[root@tango-centos02 config]# vi slave.conf
#MongoDB config - 2018.05.15

#config database path
dbpath = /usr/local/mongodb/data

#config log path
logpath = /usr/local/mongodb/logs/mongodb.log

#config port
port = 27017
bind_ip = 192.168.112.102

#config fork
fork = true

#master server
source = 192.168.112.101:27017
master = false
  • 节点3
[root@tango-centos03 config]# vi slave.conf
#MongoDB config - 2018.05.15

#config database path
dbpath = /usr/local/mongodb/data

#config log path
logpath = /usr/local/mongodb/logs/mongodb.log

#config port
port = 27017
bind_ip = 192.168.112.103

#config fork
fork = true

#master server
source = 192.168.112.101:27017
master = false
2.2 启动集群环境

1)启动主服务器和从服务器MongoDB进程

[root@tango-centos01 mongodb-linux-x86_64-rhel70-3.6.3]#./bin/mongod -f ./config/master.conf
[root@tango-centos02 mongodb-linux-x86_64-rhel70-3.6.3]# ./bin/mongod -f ./config/slave.conf
[root@tango-centos03 mongodb-linux-x86_64-rhel70-3.6.3]# ./bin/mongod -f ./config/slave.conf

2)查看进程

[root@tango-centos01 mongodb-linux-x86_64-rhel70-3.6.3]# ps -ef|grep mongo
root       1217      1  1 14:19 ?        00:00:02 ./bin/mongod -f ./config/master.conf
root       1248   1198  0 14:22 pts/0    00:00:00 grep --color=auto mongo
[root@tango-centos02 mongodb-linux-x86_64-rhel70-3.6.3]# ps -ef|grep mongo
root       1096      1  1 14:20 ?        00:00:01 ./bin/mongod -f ./config/slave.conf
root       1121   1067  0 14:22 pts/0    00:00:00 grep --color=auto mongo
[root@tango-centos03 mongodb-linux-x86_64-rhel70-3.6.3]# ps -ef|grep mongo
root       1097      1  2 14:21 ?        00:00:01 ./bin/mongod -f ./config/slave.conf
root       1122   1064  0 14:23 pts/0    00:00:00 grep --color=auto mongo

3)查看端口

[root@tango-centos01 mongodb-linux-x86_64-rhel70-3.6.3]# netstat -tlnp | grep mongod
tcp        0      0 192.168.112.101:27017   0.0.0.0:*  LISTEN      1217/./bin/mongod
[root@tango-centos02 mongodb-linux-x86_64-rhel70-3.6.3]# netstat -tlnp | grep mongod
tcp        0      0 192.168.112.102:27017   0.0.0.0:*   LISTEN      1096/./bin/mongod
[root@tango-centos03 mongodb-linux-x86_64-rhel70-3.6.3]# netstat -tlnp | grep mongod
tcp        0      0 192.168.112.103:27017   0.0.0.0:*   LISTEN      1097/./bin/mongod

4)登陆主服务器的MongoDB客户端

[[root@tango-centos01 mongodb-linux-x86_64-rhel70-3.6.3]# ./bin/mongo 192.168.112.101:27017
MongoDB shell version v3.6.3
connecting to: mongodb://192.168.112.101:27017/test
MongoDB server version: 3.6.3
Welcome to the MongoDB shell.
…
> use testuse test
switched to db test
>

5)登陆从服务器的MongoDB客户端

[root@tango-centos02 mongodb-linux-x86_64-rhel70-3.6.3]# ./bin/mongo 192.168.112.102:27017
MongoDB shell version v3.6.3
connecting to: mongodb://192.168.112.102:27017/test
MongoDB server version: 3.6.3
Welcome to the MongoDB shell.
…
> use testuse test
switched to db test
> 
2.3 集群环境验证

1)插入记录

> use master_slaveuse master_slave
switched to db master_slave
> function add(){function add(){
... var i=0;var i=0;
... for(;i<50;i++) {for(;i<50;i++) {
...   db.person.insert({"name":"wang"+i})  db.person.insert({"name":"wang"+i})
... }}
... }}
> add()add()
> db.person.find()db.person.find()
{ "_id" : ObjectId("5ad835c8eecf420e07ad281e"), "name" : "wang0" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad281f"), "name" : "wang1" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad2820"), "name" : "wang2" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad2821"), "name" : "wang3" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad2822"), "name" : "wang4" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad2823"), "name" : "wang5" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad2824"), "name" : "wang6" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad2825"), "name" : "wang7" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad2826"), "name" : "wang8" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad2827"), "name" : "wang9" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad2828"), "name" : "wang10" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad2829"), "name" : "wang11" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad282a"), "name" : "wang12" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad282b"), "name" : "wang13" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad282c"), "name" : "wang14" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad282d"), "name" : "wang15" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad282e"), "name" : "wang16" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad282f"), "name" : "wang17" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad2830"), "name" : "wang18" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad2831"), "name" : "wang19" }
Type "it" for more
>

2)在从服务器上查询表,提示错误信息:

> db.person.find()db.person.find()
Error: error: {
        "ok" : 0,
        "errmsg" : "not master and slaveOk=false",
        "code" : 13435,
        "codeName" : "NotMasterNoSlaveOk"
}
>

3)因为从节点默认不允许读写的,在从节点执行rs.slaveOk()可解决

> rs.slaveOk();;;
> db.person.find()db.person.find()
{ "_id" : ObjectId("5ad835c8eecf420e07ad281e"), "name" : "wang0" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad281f"), "name" : "wang1" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad2820"), "name" : "wang2" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad2821"), "name" : "wang3" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad2822"), "name" : "wang4" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad2823"), "name" : "wang5" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad2824"), "name" : "wang6" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad2825"), "name" : "wang7" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad2826"), "name" : "wang8" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad2827"), "name" : "wang9" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad2828"), "name" : "wang10" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad2829"), "name" : "wang11" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad282a"), "name" : "wang12" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad282b"), "name" : "wang13" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad282c"), "name" : "wang14" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad282d"), "name" : "wang15" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad282e"), "name" : "wang16" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad282f"), "name" : "wang17" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad2830"), "name" : "wang18" }
{ "_id" : ObjectId("5ad835c8eecf420e07ad2831"), "name" : "wang19" }
Type "it" for more
2.4 主从复制缺陷思考
  1. 主节点挂了能否自动切换连接?目前需要手工切换。
  2. 主节点的写压力过大如何解决?
  3. 从节点每个上面的数据都是对数据库全量拷贝,从节点压力会不会过大?
  4. 就算对从节点路由实施路由访问策略能否做到自动扩展?

参考资料

  1. MongoDB Manual
  2. 高可用的MongoDB集群

转载请注明原文地址:https://blog.csdn.net/solihawk/article/details/116203702
文章会同步在公众号“牧羊人的方向”更新,感兴趣的可以关注公众号,谢谢!
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值