MongoDB 目前的高可用架构主要有主从、复制集、以及分片,单纯的主从技术几乎被淘汰,整个稳定性以及可靠性方面复制集要比主从好,所以现在更多的会去使用复制集。在接下来的实践过程中,我们将在一台服务器(单机)实现复制集和分片。


目录

第1关:MongoDB 架构

复制集

为什么使用复制集?

分片

什么时候使用分片

第2关:MongoDB 复制集搭建

本关任务

相关知识

配置文件设置

配置主从节点

验证复制集同步

切换 Primary 节点到指定的节点

编程要求

第3关:MongoDB 分片集搭建

本关任务

相关知识

配置文件设置

route 节点

分片验证


第1关:MongoDB 架构

复制集

为什么使用复制集?

  • 备份数据

    数据库的数据只有一份的话是极不安全的,一旦数据所在的电脑坏掉,我们的数据就彻底丢失了,所以要有一个备份数据的机制。

  • 故障自动转移

    部署了复制集,当主节点挂了后,集群会自动投票再从节点中选举出一个新的主节点,继续提供服务。而且这一切都是自动完成的,对运维人员和开发人员是透明的。当然,发生故障了还是得人工及时处理,不要过度依赖复制集,万一都挂了,那就连喘息的时间都没有了。

  • 在某些特定的场景下提高读性能

    默认情况下,读和写都只能在主节点上进行。下面是MongoDB的客户端支持5种复制集读选项:

    • nearest :读操作会在复制集中网络延时最小的节点上进行,与节点类型无关。

    • secondaryPreferred :在大多数情况下,读操作都是在从节点上进行的,但是当从节点不可用了,读操作会转移到主节点上进行;

    • secondary :所有的读操作都在复制集的从节点上执行;

    • primaryPreferred :在大多数情况时,读操作在主节点上进行,但是如果主节点不可用了,读操作就会转移到从节点上执行;

    • primary :默认模式,所有的读操作都在复制集的主节点进行的;

复制集结构,如图:

分片

分片(sharding)是指将数据库拆分,使其分散在不同的机器上的过程。将数据分散到不同的机器上,不需要功能强大的服务器就可以存储更多的数据和处理更大的负载。基本思想就是将集合切成小块,这些块分散到若干片里,每个片只负责总数据的一部分,最后通过一个均衡器来对各个分片进行均衡(数据迁移)。通过一个名为 mongos 的路由进程进行操作,mongos 知道数据和片的对应关系(通过配置服务器)。

什么时候使用分片

  • 机器的磁盘不够用了,使用分片解决磁盘空间的问题;

  • 单个 mongod 已经不能满足写数据的性能要求,通过分片让写压力分散到各个分片上面,使用分片服务器自身的资源;

  • 想把大量数据放到内存里提高性能,通过分片使用分片服务器自身的资源。

分片结构,如图:

上图中主要有如下所述三个主要组件:

  • Shard :用于存储实际的数据块,实际生产环境中一个 shard server 角色可由几台机器组个一个 replica set 承担,防止主机单点故障;

  • Config Server :mongod 实例,存储了整个 ClusterMetadata,其中包括 chunk 信息;

  • Query Routers :前端路由,客户端由此接入,且让整个集群看上去像单一数据库,前端应用可以透明使用。

编程要求

1、为什么要使用复制集?A、备份数据✔B、提高写性能C、提高读性能✔D、故障自动转移✔2、什么时候使用分片?A、磁盘空间不够用✔B、无法满足写数据的性能要求✔C、无法满足读数据的性能要求D、大量数据放到内存里提高性能✔

第2关:MongoDB 复制集搭建

本关任务

按照编程要求搭建复制集。

相关知识

为了完成本关任务,你需要掌握:

1.如何设置配置文件启动服务;

2.如何配置主从节点;

3.如何验证复制集同步;

4.如何手动切换 Primary 节点到指定的节点。

我们在一台虚拟机中启动三个 mongodb 服务,来模拟多台服务器协同工作的情况。

选用三个端口连接数据库:27018、27019、27020。

配置文件设置

因为我们要启动三个 mongodb 服务,所以要准备三个数据存放位置,三个日志文件,三个配置文件。

  • 数据存放位置;

    在 /data 路径下创建文件夹 db1、db2 和 db3 来存放三个服务的数据。

    root@evassh-13183285:~# mkdir /data/db1root@evassh-13183285:~# mkdir /data/db2root@evassh-13183285:~# mkdir /data/db3
  • 日志文件;

    在 /logs 路径下创建文件夹 mongo 存放日志文件 mongod1.log、mongod2.log 和 mongod3.log(文件不用创建,到时候会自动生成,但路径即文件夹必须提前创建好)。

    root@evassh-13183285:~# mkdir /logsroot@evassh-13183285:~# mkdir /logs/mongo
  • 配置文件;

    在 /etc/mongod 路径下新建三个配置文件,使用配置文件启动 mongod 服务(在之前的实训中我们都是用命令启动的)。

    root@evassh-13183285:~# mkdir /etc/mongodroot@evassh-13183285:~# cd /etc/mongodroot@evassh-13183285:/etc/mongod# vim mongod1.conf

    mongod1.conf 内容如下:

    port=27018#配置端口号

    dbpath=/data/db1#配置数据存放的位置

    logpath=/logs/mongo/mongod1.log #配置日志存放的位置

    logappend=true #日志使用追加的方式

    fork=true #设置在后台运行

    replSet=YOURMONGO #配置复制集名称,该名称要在所有的服务器一致

    root@evassh-13183285:/etc/mongod# vim mongod2.conf

    mongod2.conf 内容如下:

    port=27019 #配置端口号

    dbpath=/data/db2 #配置数据存放的位置

    logpath=/logs/mongo/mongod2.log #配置日志存放的位置

    logappend=true #日志使用追加的方式

    fork=true #设置在后台运行

    replSet=YOURMONGO #配置复制集名称,该名称要在所有的服务器一致

    root@evassh-13183285:/etc/mongod# vim mongod3.conf

    mongod3.conf 内容如下:

    port=27020#配置端口号

    dbpath=/data/db3 #配置数据存放的位置

    logpath=/logs/mongo/mongod3.log #配置日志存放的位置

    logappend=true #日志使用追加的方式

    fork=true #设置在后台运行

    replSet=YOURMONGO #配置复制集名称,该名称要在所有的服务器一致

以上工作准备完成,便可以开启服务了,配置文件启动命令(在命令行中输入):

mongod -f /etc/mongod/mongod1.confmongod -f /etc/mongod/mongod2.confmongod -f /etc/mongod/mongod3.conf

具体效果如图所示:

配置主从节点

三个端口的服务全部启动成功后,需要进入其中一个进行配置节点。 设置27019为 arbiter 节点。

  • 进入端口号为27018的进行配置,连接数据库:mongo –port 27018;

  • 选择数据库 admin;

  • 输入配置要求如下:

    config = {_id:"YOURMONGO",members:[{_id:0,host:'127.0.0.1:27018'},{_id:1,host:'127.0.0.1:27019',arbiterOnly:true},{_id:2,host:'127.0.0.1:27020'}]}
  • 使用 rs.initiate(config)进行初始化:rs.initiate(config)

    如上所示配置成功后,不同端口的数据库登陆后左边的>可能变为如下两种状态:

    • 说明该端口为主节点,如图所示:

      YOURMONGO:PRIMARY> 
    • 说明该端口为从节点,如图所示:

      YOURMONGO:SECONDARY> 
  • 使用 rs.status() 查看状态。

验证复制集同步

在主数据库插入数据,然后去从数据库查看数据是否一致。

连接主数据库:mongo –port 27018;

use testdb.person.insert({name:'王小明',age:20})

具体步骤如图5所示:

连接从数据库:mongo –port 27020; 从库查询数据需要设置 slaveOk 为 true;

use testrs.slaveOk(true)db.person.find()

具体步骤如图6所示:

至此复制集搭建完成,主数据库的数据的更新后,从数据库的数据也会同步更改,一旦主数据库挂掉,从数据库可自动变为主数据库,极大地保障了数据的安全,这也是搭建复制集的必要性。

切换 Primary 节点到指定的节点

在实际应用中,如果想指定某服务器或端口作为主节点,而不是随机选举一个主节点,可以通过以下方法改变 Primary 节点:

  • 先进入主节点中进行操作:mongo –port 27018
  • 查看目前的节点状态:
    rs.conf() #查看配置rs.status() #查看状态

    其中 priority : 是优先级,默认为 1,优先级 0 为被动节点,不能成为活跃节点。优先级不为 0 则按照由大到小选出活跃节点。因为默认的都是1,所以只需要把给定的服务器的 priority 加到最大即可。让27020成为主节点,操作如下: 现进入目前的主节点进行操作如下:

cfg=rs.conf()cfg.members[2].priority=2 #修改priority,members[2]即对应27020端口rs.reconfig(cfg) #重新加载配置文件,强制了副本集进行一次选举,优先级高的成为Primary。在这之间整个集群的所有节点都是secondaryrs.status()

这样,给定的服务器或端口就成为了主节点。

编程要求

根据提示,仿照实训中的例子,在右侧命令行进行操作,搭建复制集,要求如下:

  • 数据存放路径为:/data/test/db1、/data/test/db2 和 /data/test/db3;

  • 日志存放路径为:/logs/test/mongod1.log、/logs/test/mongod2.log和 /logs/test/mongod3.log;

  • 配置文件所在路径为:/etc/test/mongod1.conf、/etc/test/mongod2.conf 和 /etc/test/mongod3.conf;

  • 端口选用20001、20002和20003,其中要求20001成为主节点,20002为 arbiter 节点。

root@evassh-13183285:~# mkdir /data/testroot@evassh-13183285:~# mkdir /data/test/db1root@evassh-13183285:~# mkdir /data/test/db2root@evassh-13183285:~# mkdir /data/test/db3root@evassh-13183285:~# mkdir /logsroot@evassh-13183285:~# mkdir /logs/testroot@evassh-13183285:~# cd /etcroot@evassh-13183285:/etc# mkdir /etc/testroot@evassh-13183285:/etc# cd /etc/testroot@evassh-13183285:/etc/test# vim mongod1.confroot@evassh-13183285:/etc/test# mongod -f /etc/test/mongod1.confroot@evassh-13183285:/etc/test# vim mongod2.confroot@evassh-13183285:/etc/test# mongod -f /etc/test/mongod2.confroot@evassh-13183285:/etc/test# vim mongod3.confroot@evassh-13183285:/etc/test# mongod -f /etc/test/mongod3.conf

mongod1.conf内容:

port=20001
dbpath=/data/test/db1
logpath=/logs/test/mongod1.log
logappend=true
fork=true
replSet=YOURMONGO

mongod2.conf内容:

port=20002
dbpath=/data/test/db2
logpath=/logs/test/mongod2.log
logappend=true
fork=true
replSet=YOURMONGO

mongod3.conf内容:

port=20003
dbpath=/data/test/db3
logpath=/logs/test/mongod3.log
logappend=true
fork=true
replSet=YOURMONGO

> use adminswitched to db admin> config = {_id:"YOURMONGO", members:[{_id:0,host:'127.0.0.1:20001'},{_id:1,host:'127.0.0.1:20002',arbiterOnly:true},{_id:2,host:'127.0.0.1:20003'}]}> rs.initiate(config)YOURMONGO:SECONDARY> cfg=rs.conf()YOURMONGO:PRIMARY> cfg.members[2].priority=22YOURMONGO:PRIMARY> rs.reconfig(cfg)YOURMONGO:PRIMARY> rs.status()YOURMONGO:PRIMARY> 

第3关:MongoDB 分片集搭建

本关任务

按照编程要求搭建分片集。

相关知识

为了完成本关任务,你需要掌握:

1.用配置文件启动服务;

2.如何配置 config 节点;

3.如何配置 route 节点;

4.如何验证分片集。

:分片实际是在多台机器配置的,由于评测原因我们在一台机子上模拟,其步骤和原理相同。

配置文件设置

  • 同复制集一样,我们要准备目录存放我们的数据和日志:

mkdir -p /data/shard1/db

mkdir -p /logs/shard1/log

mkdir -p /data/shard2/db

mkdir -p /logs/shard2/log

mkdir -p /data/shard3/db

mkdir -p /logs/shard3/log

mkdir -p /data/config/db

mkdir -p /logs/config/log

mkdir -p /logs/mongs/log

  • 配置文件 (新建在 /etc/mongo 目录下);

mongod1.conf 内容如下:

dbpath=/data/shard1/db

logpath=/logs/shard1/log/mongodb.log

port=10001

shardsvr=true

fork=true

mongod2.conf 内容如下:

dbpath=/data/shard2/db

logpath=/logs/shard2/log/mongodb.log

port=10002

shardsvr=true

fork=true

mongod3.conf 内容如下:

dbpath=/data/shard3/db

logpath=/logs/shard3/log/mongodb.log

port=10003

shardsvr=true

fork=true

其中 shardsvr 是用来开启分片的。

  • 从配置文件启动 mongod 服务:

mongod -f /etc/mongo/mongod1.conf

mongod -f /etc/mongo/mongod2.conf

mongod -f /etc/mongo/mongod3.conf

config 节点

  • 配置启动节点服务:

mongod –dbpath /data/config/db –logpath /logs/config/log/mongodb.log –port 10004 –configsvr –replSet cs –fork

  • 连接 route 节点:mongo localhost:10004
  • 输入以下命令:

use admin

cfg = {_id:’cs’,configsvr:true,members:[{_id:0,host:’localhost:10004′}]}

rs.initiate(cfg)

运行效果如图所示,说明设置成功:

route 节点

  • 配置启动节点服务:

mongos –configdb cs/localhost:10004 –logpath /logs/mongs/log/mongodb.log –port 10005 –fork

  • 连接上 route 节点:mongo localhost:10005
  • 添加分片:

sh.addShard(‘localhost:10001’)

sh.addShard(‘localhost:10002’)

sh.addShard(‘localhost:10003’)

  • 查看集群的状态:分片摘要信息、数据库摘要信息、集合摘要信息等;

sh.status()

运行效果如图所示,说明设置成功:

分片验证

  • 连接 route 节点:mongo localhost:10005;

数据量太小可能导致分片失败,这是因为 chunksize 默认的大小是 64MB( chunkSize 来制定块的大小,单位是 MB ),使用以下代码把 chunksize 改为 1MB 后,插入数据,便可以分片成功。

use config

db.settings.save( { _id:”chunksize”, value: 1 } )

  • 对集合使用的数据库启用分片:sh.enableSharding(“test”)

  • 添加索引:db.user.ensureIndex({ “uid” : 1})

  • 分片:sh.shardCollection(“test.user”,{“uid” : 1})

  • 插入10万条数据(大概需要40s 左右):[要特别特别久]

use test

for(i=0;i<100000;i++){db.user.insert({uid:i,username:'test-'+i})}

  • 再次运行 sh.status() 会多出如图内容,显示了分片的情况。

  • 去各个节点查看数据分布情况:

以下分别是在端口10001、10002和10003查询的文档条数,加起来正好10万条。(这里我试了几次,每次都比100000多几个,不知道为什么….)

编程要求

根据提示,仿照实训中的例子,在右侧命令行进行操作,搭建分片,要求如下:

  • 数据、日志和配置文件存放路径如下:
    1. mkdir -p /data/test2/shard1/db
    2. mkdir -p /logs/test2/shard1/log
    3. mkdir -p /data/test2/shard2/db
    4. mkdir -p /logs/test2/shard2/log
    5. mkdir -p /data/test2/shard3/db
    6. mkdir -p /logs/test2/shard3/log
    7. mkdir -p /data/test2/config/db
    8. mkdir -p /logs/test2/config/log
    9. mkdir -p /logs/test2/mongs/log
    10. mkdir -p /etc/test2
  • 端口选用21001、21002、21003、21004和21005,其中要求21004成为 config 节点,21005为 route 节点。

注意:再次点击测评前删除数据库中的所有索引 db.collection.dropIndexes(),防止影响测评结果。