Mongodb分片

MongoDB分片是MongoDB支持的另一种集群形式,它可以满足MongoDB数据量呈爆发式增长的需求。当MongoDB存储海量的数据时,一台机器可能无法满足数据存储的需求,也可能无法提供可接受的读写吞吐量,这时,我们就可以通过在多台机器上对海量数据进行划分(即分片),使得MongoDB数据库系统能够存储和处理更多的数据。

分片概述

分片(Sharding)技术是开发人员用来提高数据存储和数据读写吞吐量常用的技术之一。简单的来说,分片主要是将数据进行划分后,将它们分别存放于不同机器上的过程。通过使用分片可以实现降低单个机器的压力和处理更大的数据负载功能。分片与副本集主要区别在于,分片是每个节点存储数据的不同片段,而副本集是每个节点存储数据的相同副本。

所有数据库都可以进行手动分片(Manual Sharding),因此,分片并不是MongoDB特有的。不同类型的数据均可以通过人为操作被分配到不同的数据库服务器上,然而,人工分片是需要编写相关代码来实现分片功能,并且还不容易维护(如集群中节点发生变动的情况)。MongoDB数据库可以实现自动分片,它内置了多种分片逻辑,使得MongoDB可以自动处理分片上数据的分布,也可以很容易的管理分片集群。

由于数据量太大,导致本地磁盘不足以存储的情况;为了提高数据库性能,从而将海量数据存储在内存中,导致单个MongoDB数据库内存不足的情况;若是出现数据请求量太大,导致单MongoDB机器不能满足读写数据的性能情况。若是出现这三种情况,我们就可以使用MongoDB的分片技术来解决。

分片策略

MongoDB之所以能够实现自动分片,这是因为其内置了分片策略。MongoDB通过分片键(Shard Key)将集合中的数据划分为多个块(Chunk)(默认大小为64MB,每个块均表示集合中数据的一部分),然后MongoDB根据分片策略将划分的块分发到分片集群中。需要注意,分片键可以是集合文档中的一个或多个字段。

MongoDB的分片策略主要包括范围分片和哈希分片两种,介绍如下:

  1. 范围分片(Range Sharding)

MongoDB根据分片键的值范围将数据划分为不同块,每个分片都包含了分片键在一定范围内的数据。这样的话,若有文档写入时,MongoDB会根据该文档的分片键,从而交由指定分片服务器去处理。

若文档分片键的值范围在[minKey,10)中,则该文档需要交由分片服务器A进行相关处理;若文档分片键的值范围在[10,20)中,则该文档需要交由分片服务器B进行相关处理;若文档分片键的值范围在[20,maxKey)中,则该文档需要交由分片服务器C进行相关处理。 使用基于范围分片时,拥有相近分片键的文档会存储在同一个分片服务器中,从而提升范围查询的效率。但是,当插入批量文档时,分片键集中在一定范围内,就会导致数据分布不均匀,从而导致其中一个分片服务器负载过重。

MongoDB的分片原理 mongodb对已有的数据分片_nosql

  1. 哈希分片(Hash Sharding)

哈希分片类似于范围分片,两者的区别在于范围分片是MongoDB根据分片键的值直接进行范围划分,而哈希分片则先将分片键的值进行哈希计算后,然后对这些哈希值进行范围划分,从而使得每个分片都包含了哈希值在一定范围内的数据;范围分片可以支持复合分片键,而哈希分片只支持单个字段作为分片键。哈希值的随机性,使得数据随机分布在分片集群中不同分片服务器上。

MongoDB的分片原理 mongodb对已有的数据分片_数据库_02

从图中可以看出,若文档分片键的哈希值为5,则该文档需要交由分片服务器A进行相关处理;若文档分片键的哈希值为12,则该文档需要交由分片服务器B进行相关处理;若文档分片键的哈希值为23,则该文档需要交由分片服务器C进行相关处理。 使用基于哈希分片时,拥有“相近”分片键的文档不会存储在同一个分片服务器中,这样的话,数据的分离性会更好,可以保证分片集群中数据分布均衡。但是,由于数据是通过哈希计算进行随机存放的,因此会降低查询性能。

分片集群架构

在MongoDB分片集群中,只有各组件间的协同工作,才可使得分片集群正常运行。在学习分片集群的操作之前,有必要先来学习一下分片集群架构。

MongoDB的分片原理 mongodb对已有的数据分片_nosql_03

从图中可以看出,分片集群中主要由三个部分组成,即分片服务器(Shard)、路由服务器(Mongos)以及配置服务器(Config Server)组成。其中,分片服务器有三个,即Shard1、Shard2、Shard3;路由服务器有两个,即Mongos1和Mongos2;配置服务器有三个,即主、副、副。下面,我们针对分片集群架构中的组成部分进行详细介绍,具体如下:

分片服务器

即MongoDB实例(即mongod,用Shard表示),分片服务器是实际存储数据的组件,持有完整数据集中的一部分,每个分片服务器都可以是一个MongoDB实例,也可是一组MongoDB实例组成的集群(副本集)。从MongoDB 3.6开始,必须将分片部署为副本集,这样具有更好的容错性。

路由服务器

即mongos,路由服务器主要提供客户端应用程序与分片集群交互的接口,所有请求都需要通过路由服务器进行协调工作。路由服务器实际上就是一个消息分发请求中心,它负责把客户端应用程序对应的数据请求转发到对应的分片服务器上。应用程序将查询、存储、更新等请求原封不动地发送给路由服务器。路由服务器询问配置服务器操作分片服务器需要获取哪些元数据,然后连接相应的分片服务器进行相关操作,最后将各个分片服务器的响应进行合并,返回给客户端应用程序。
生产环境中,一个分片集群通常会有多个路由服务器,一方面可以解决多个客户端同时请求,从而达到负载均衡的效果;另一方面可以解决当路由服务器宕机时导致整个分片集群无法使用的问题。

配置服务器

即Config Server。在生产环境中,通常需要多个配置服务器,因为它存储了分片集群的元数据,并且这些数据是不允许丢失的。因此,需要配置多个配置服务器以防止数据丢失,尽管其中一台分片服务器宕机,我们还有其它配置服务器,从而保证MongoDB分片集群依然能够正常工作。从MongoDB 3.4版本开始,配置服务器必须部署副本集,因此我们需要配置三个配置服务器组成的副本集。
配置服务器存储着分片集群的持久化元数据,而路由服务器存储着分片集群的非持久化元数据,这些数据均为内存缓存的数据。当路由服务器初次启动或关闭重启时,就会从配置服务器中加载分片集群的元数据。若是配置服务器的信息发生变化,则会通知所有路由服务器更新自己的状态,这样路由服务器就能继续准确的协调客户端与分片集群的交互工作。

部署分片集群

环境准备

从图中可以看出,为了保证不同虚拟机中资源的平均分配,我们在三台虚拟机中分别部署了副本集的不同节点,即虚拟机NoSQL_1中包含主节点Shard1、副节点shard2和仲裁节点Shard3,虚拟机NoSQL_2中包含仲裁节点Shard1、主节点Shard2和副节点Shard3,虚拟机NoSQL_3中包含副节点Shard1、仲裁节点Shard2和主节点Shard3。注意,若是在单台虚拟机中部署分片副本集的三个主节点或者三个仲裁节点,则会导致该台虚拟机性能过大或性能空闲。

由于部署分片集群时,每台虚拟机都要启动不同的服务进程,因此部署分片集群之前,需要清楚每台虚拟机的服务端口号所表示的服务,从而避免出现端口冲突的情况。接下来,我们通过一张表来介绍分片集群中服务端口号的分配情况,如表所示。

MongoDB的分片原理 mongodb对已有的数据分片_数据库_04


为了规范MongoDB分片集群相关服务器的数据文件、配置文件以及日志文件,这里我们通过使用user_mongo用户分别在服务器nosql01、nosql02、nosql03的根目录下创建一些文件夹作为约定(若服务器不存在user_mongo用户,则创建user_mongo用户,并授权;将目录/opt/servers/mongodb_demo/更改为用户user_mongo权限),具体如下:

mkdir -p /opt/servers/mongodb_demo/shardcluster/
mkdir -p /opt/servers/mongodb_demo/shardcluster/configServer/configFile
mkdir -p /opt/servers/mongodb_demo/shardcluster/configServer/data
mkdir -p /opt/servers/mongodb_demo/shardcluster/configServer/logs
mkdir -p /opt/servers/mongodb_demo/shardcluster/shard/configFile
mkdir -p /opt/servers/mongodb_demo/shardcluster/shard/shard1_data
mkdir -p /opt/servers/mongodb_demo/shardcluster/shard/shard2_data
mkdir -p /opt/servers/mongodb_demo/shardcluster/shard/shard3_data
mkdir -p /opt/servers/mongodb_demo/shardcluster/shard/logs
mkdir -p /opt/servers/mongodb_demo/shardcluster/mongos/configFile
mkdir -p /opt/servers/mongodb_demo/shardcluster/mongos/logs

接下来,我们需要分别在三台服务器(nosql01、nosql02、nosql03)的配置服务器、分片服务器以及路由服务器的日志目录下,创建对应的日志管理文件。这里我们以服务器nosql为例,具体如下:

# 配置服务器日志管理文件
touch /opt/servers/mongodb_demo/shardcluster/configServer/logs/config_server.log
touch /opt/servers/mongodb_demo/shardcluster/shard/logs/shard1.log
touch /opt/servers/mongodb_demo/shardcluster/shard/logs/shard2.log
touch /opt/servers/mongodb_demo/shardcluster/shard/logs/shard3.log
touch /opt/servers/mongodb_demo/shardcluster/mongos/logs/mongos.log

执行上述命令后,查看是否成功创建配置服务器、分片服务器(1、2、3)、路由服务器的日志管理文件,这里以查看服务器nosql01上的配置服务器日志管理文件为例进行展示,具体效果如图所示。

MongoDB的分片原理 mongodb对已有的数据分片_mongodb_05


从图中可以看出,我们已经成功创建配置服务器的日志管理文件。(注:重复上述步骤,在服务器nosql02和服务器nosql03根目录下创建同样的目录结构以及日志管理文件,这里不再赘述)。至此,我们完成了MongoDB分片集群的环境准备工作。

部署MongoDB

由于MongoDB分片集群是基于MongoDB的不同角色组建的,因此部署MongoDB分片集群的基础仍是部署MongoDB。部署MongoDB的步骤如下:
(1)将MongoDB安装包上传到服务器nosql01的/opt/software/目录下。
(2)将MongoDB安装包的用户和用户组权限修改为user_mongo。
(3)解压安装MongoDB,将MongoDB安装包解压到目录/opt/servers/mongo_demo/shardcluster/下。
(4)解压完MongoDB安装包后,进入到/opt/servers/mongodb_demo/shardcluster目录,如果觉得解压后的文件名过长,可以对文件进行重命名。
(5)分发集群配置文件。将服务器nosql01上用于存放分片集群相关配置文件、日志文件和数据文件等相关内容的目录shardcluster分发到服务器nosql02和nosql03上。

具体命令如下:

tar -zxvf /opt/software/mongodb-linux-x86_64-rhel70-4.2.2.tgz -C /opt/servers/mongodb_demo/shardcluster/
cd /opt/servers/mongodb_demo/shardcluster/
mv mongodb-linux-x86_64-rhel70-4.2.2/ mongodb
scp -r /opt/servers/mongodb_demo/shardcluster/mongodb/ user_mongo@nosql02:/opt/servers/mongodb_demo/shardcluster/mongodb/
scp -r /opt/servers/mongodb_demo/shardcluster/mongodb/ user_mongo@nosql03:/opt/servers/mongodb_demo/shardcluster/mongodb/

执行上述命令后,需要按照提示内容连接服务器并且输入用户user_mongo的密码,即123456,按照提示输入后,服务器nosql01的mongodb目录会分发到服务器nosql02和nosql03上,具体如图所示。

MongoDB的分片原理 mongodb对已有的数据分片_数据库_06

部署Config Server

上一小节完成了MongoDB的部署。本节我们将部署Config Server,具体步骤如下:

创建配置文件

首先,使用user_mongo用户进入服务器nosql01的/configServer/configFile/目录下,创建配置文件mongodb_config.conf,用于启动配置服务器,具体命令如下:

touch /opt/servers/mongodb_demo/shardcluster/configServer/configFile/mongodb_config.conf

然后,编辑配置文件mongodb_config.conf,添加配置服务器的相关参数。

vim  /opt/servers/mongodb_demo/shardcluster/configServer/configFile/mongodb_config.conf
#数据文件存放位置
dbpath=/opt/servers/mongodb_demo/shardcluster/configServer/data
#日志文件
logpath=/opt/servers/mongodb_demo/shardcluster/configServer/logs/config_server.log
#端口号
port=27022
#绑定服务IP
bind_ip=nosql01
#使用追加的方式写日志
logappend=true
#以守护进程的方式运行MongoDB
fork=true
#最大同时连接数
maxConns=5000
#复制集名称
replSet=configs
#声明这是一个集群的ConfigServer
configsvr=true

最后,将配置文件mongodb_config.conf通过scp命令分发到服务器nosql02和nosql03的目录configFile下,具体命令如下:

#分发到服务器nosql02
scp /opt/servers/mongodb_demo/shardcluster/configServer/configFile/mongodb_config.conf user_mongo@nosql02:/opt/servers/mongodb_demo/shardcluster/configServer/configFile/
#分发到服务器nosql03
scp /opt/servers/mongodb_demo/shardcluster/configServer/configFile/mongodb_config.conf user_mongo@nosql03:/opt/servers/mongodb_demo/shardcluster/configServer/configFile/

这里需要注意的是,参数bind_ip是根据当前服务器的IP地址或主机名进行修改的。执行上述命令后,我们必须修改服务器nosql02和nosql03配置文件mongodb_config.conf中的参数bind_ip的值,即将bind_ip的值修改为对应服务器的IP地址或主机名。

启动Config Server

分别在三台服务器(即nosql01、nosql02、nosql03)中MongoDB的bin目录下启动Config Server,具体命令如下:

cd /opt/servers/mongodb_demo/shardcluster/mongodb/bin
./mongod -f /opt/servers/mongodb_demo/shardcluster/configServer/configFile/mongodb_config.conf

执行上述命令后,控制台会输出Config Server服务启动信息,若出现“successfully”,则说明Config Server启动成功,如图所示。

配置Config Server副本集

待三台服务器的Config Server启动完成后,选择任意一台服务器通过MongoDB客户端对Config Server进行初始化副本集的操作,这里以服务器nosql01为例,在MongoDB的bin目录下登录MongoDB客户端,并进行初始化,命令如下。

./mongo --host nosql01 --port 27022
> rs.initiate()
configs:SECONDARY> rs.add('nosql2:27022')
configs:PRIMARY> rs.add('nosql03:27022')

执行上述命令后,查看控制台输出信息,如图所示。

MongoDB的分片原理 mongodb对已有的数据分片_mongodb_07


我们可通过执行“rs.status()”命令查看副本集状态,从而判断副本集是否部署成功。至此,完成分片集群中以副本集模式部署Config Server。

部署shard

创建配置文件

在服务器nosql01的/shard/configFile目录下,创建三个配置文件mongodb_shard1.conf、mongodb_shard2.conf和mongodb_shard3.conf,用于启动副本集模式的Shard,具体命令如下:

touch /opt/servers/mongodb_demo/shardcluster/shard/configFile/mongodb_shard1.conf
touch /opt/servers/mongodb_demo/shardcluster/shard/configFile/mongodb_shard2.conf
touch /opt/servers/mongodb_demo/shardcluster/shard/configFile/mongodb_shard3.conf

执行上述命令后,再执行“ll”命令,查看三个配置文件是否创建成功。
执行“vi”命令,在配置文件mongodb_shard1.conf中添加分片服务器1的相关参数。

cd /opt/servers/mongodb_demo/shardcluster/shard/configFile/
vi mongodb_shard1.conf
#数据文件存放位置
dbpath=/opt/servers/mongodb_demo/shardcluster/shard/shard1_data
#日志文件
logpath=/opt/servers/mongodb_demo/shardcluster/shard/logs/shard1.log
#端口号
port=27018
#使用追加的方式写日志
logappend=true
#以守护进程的方式运行MongoDB
fork=true
#最大同时连接数
maxConns=5000
#绑定服务IP
bind_ip=nosql01
#声明开启分片
shardsvr=true
#指定集名称
replSet=shard1

在配置文件mongodb_shard1.conf中添加完上述内容后。

重复执行“vi”命令,在配置文件mongodb_shard2.conf和mongodb_shard3.conf中添加分片服务器的相关参数。

执行上述操作后,至此,我们完成对服务器nosql01中分片集群的Shard配置。

重复nosql01中Shard配置过程,完成对服务器nosql02,nosql03的shard配置。

具体参数,可以按照此表来,大家也可以自行分配端口。

MongoDB的分片原理 mongodb对已有的数据分片_nosql_08

启动Shard

分别在三台服务器(nosql01、nosql02、nosql03)中MongoDB的bin目录下启动Shard,具体命令如下:

cd /opt/servers/mongodb_demo/shardcluster/mongodb/bin
./mongod -f /opt/servers/mongodb_demo/shardcluster/shard/configFile/mongodb_shard1.conf
./mongod -f /opt/servers/mongodb_demo/shardcluster/shard/configFile/mongodb_shard2.conf
./mongod -f /opt/servers/mongodb_demo/shardcluster/shard/configFile/mongodb_shard3.conf

三台服务器启动Shard时,控制台均输出“child process started successfully”的信息,因此说明我们成功启动Shard。

配置Shard副本集

三台虚拟机的Shard启动完成后,通过MongoDB客户端分别对三台服务器中的分片进行初始化副本集的操作,具体操作步骤如下。
首先,在服务器nosql01中登录MongoDB客户端,对分片服务器Shard1进行初始化副本集操作(副本集分片Shard1的主节点位于服务器nosql01),具体命令如下:

# 在MongoDB的bin目录下执行
$ ./mongo --host nosql01 --port 27018
# 初始化,设置本机为副本集主节点
> rs.initiate()
# 添加副节点
shard1:SECONDARY> rs.add('nosql02:27019')
# 添加仲裁节点
shard1:PRIMARY> rs.addArb('nosql03:27020')

执行上述命令后,我们就完成了分片服务器Shard1中副本集的初始化配置。注:我们可通过执行“rs.status()”命令查看副本集状态。
然后,在服务器nosql02中登录MongoDB客户端,对分片服务器Shard2进行初始化副本集操作(副本集分片Shard2的主节点位于服务器nosql02),具体命令如下:

#在MongoDB的bin目录下执行
$ ./mongo --host nosql02 --port 27018
#初始化,设置本机为副本集主节点
> rs.initiate()
#添加副节点
shard2:SECONDARY> rs.add('nosql03:27019')
#添加仲裁节点
shard2:PRIMARY> rs.addArb('nosql01:27020')

执行上述命令后,我们就完成了分片服务器Shard2中副本集的初始化配置。注:我们可通过执行“rs.status()”命令查看副本集状态。
最后,在服务器nosql03中登录MongoDB客户端,对分片服务器Shard3进行初始化副本集操作(副本集分片Shard3的主节点位于服务器nosql03),具体命令如下:

#在MongoDB的bin目录下执行
$ ./mongo --host nosql03 --port 27018
#初始化,设置本机为副本集主节点
> rs.initiate()
#添加副节点
shard3:SECONDARY> rs.add('nosql01:27019')
#添加仲裁节点
shard3:PRIMARY> rs.addArb('nosql02:27020')

执行上述命令后,我们就完成了分片服务器Shard3中副本集的初始化配置。注:我们可通过执行“rs.status()”命令查看副本集状态。
至此,我们完成了分片集群中三个Shard的部署,并且每个Shard以副本集模式运行。

部署mongos

创建配置文件

在服务器nosql01的/mongos/configFile目录下,创建配置文件mongodb_mongos.conf,用于启动mongos,具体命令如下:

touch /opt/servers/mongodb_demo/shardcluster/mongos/configFile/mongodb_mongos.conf
vi /opt/servers/mongodb_demo/shardcluster/mongos/configFile/mongodb_mongos.conf

执行“vi”命令,在配置文件mongodb_mongos.conf中添加路由服务器的相关参数,具体如下:

logpath=/opt/servers/mongodb_demo/shardcluster/mongos/logs/mongos.log
logappend=true
port=27021
bind_ip=nosql01
fork=true
#指定配置服务器(Config Server)地址
configdb =configs/nosql01:27022,nosql02:27022,nosql03:27022
maxConns=20000

上述内容中,我们没有设置参数dbpath,这是因为路由服务器不需要存储数据目录,因此不需要设置参数dbpath。
由于在分片集群中规划了两个mongos,因此,需要将配置文件mongodb_mongos.conf通过scp命令分发至服务器nosql02的目录/mongos/configFile下,具体命令如下:

scp /opt/servers/mongodb_demo/shardcluster/mongos/configFile/mongodb_mongos.conf user_mongo@nosql02:/opt/servers/mongodb_demo/shardcluster/mongos/configFile/

执行上述命令后,我们需要修改服务器nosql02的配置文件mongodb_mongos.conf中参数bind_ip的值,即将值修改为当前服务器的IP地址或主机名(即nosql02)。

启动mongos服务

分别在两台服务器(nosql01和nosql02)中MongoDB的bin目录下启动mongos,具体命令如下:

cd /opt/servers/mongodb_demo/shardcluster/mongodb/bin
./mongos -f /opt/servers/mongodb_demo/shardcluster/mongos/configFile/mongodb_mongos.conf

两台服务器启动mongos时,控制台均输出“child process started successfully”的信息,说明我们成功启动mongos,从而确保分片集群中至少包含两个mongos。

启动分片功能

分片集群部署完成后,还需要启动分片功能。下面,我们来启动分片集群的分片功能,具体步骤如下。

(1)在服务器nosql01中登录mongos的MongoDB客户端(需要通过mongos操作分片集群),具体命令如下:
(2)切换到数据库gateway,具体命令如下:
(3)向分片集群中添加三个Shard,分别为shard1、shard2和shard3,具体命令如下:

# 在MongoDB的bin目录下执行
$ ./mongo --host nosql01 --port 27021
mongos> use gateway
switched to db gateway
mongos> sh.addShard("shard1/nosql01:27018,nosql02:27019,nosql03:27020")
{.......}
mongos> sh.addShard("shard2/nosql01:27020,nosql02:27018,nosql03:27019") 
{.......}
mongos> sh.addShard("shard3/nosql01:27019,nosql02:27020,nosql03:27018")
{.......}

执行上述命令后,控制台会返回当前添加Shard操作是否成功的信息,若信息中出现字段“OK”的值为1,则说明当前Shard添加成功。

分片的基本操作

我们启动了分片集群的分片功能。若此时向分片集群添加数据库和集合时,默认情况下这些集合和数据库是没有实现分片功能的。接下来,我们将详细讲解如何实现对数据库和集合进行分片操作,具体操作步骤如下。
(1)登录MongoDB客户端
在服务器nosql01中登录mongos的MongoDB客户端,具体命令如下:

在MongoDB的bin目录下执行
$ ./mongo --host nosql01 --port 27021

(2)设置chunk
为了便于展示分片操作,将分片chunk(块)设置为1M,使得插入少量数据就可体现出分片的效果,具体命令如下:

# 切换到数据库config 
mongos> use config
switched to db config
# 设置块大小为1M
mongos> db.settings.save({"_id":"chunksize","value":1})
WriteResult({ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : "chunksize"

(3)模拟写入数据
在分片集群中,创建数据库school,并向数据库中添加集合user,然后模拟向集合中写入五万条文档,具体命令如下:

#切换(创建)数据库school 
mongos> use school
switched to db school
#向集合user中添加5万条文档
mongos> for(i=1;i<=50000;i++){db.user.insert({"id":i,"name":"jack"+i})}
WriteResult({ "nInserted" : 1 })

(4)对数据库进行分片操作
在开启集合分片前,需要先开启数据库的分片功能,具体命令如下。

#切换到数据库gateway 
mongos> use gateway
switched to db gateway
#实现数据库school分片功能
mongos> sh.enableSharding("school")
{......}

执行上述命令后,若是控制台返回“ok:1”,则说明我们成功开启数据库分片功能,即成功对数据库进行分片操作。注:我们需要在数据库gateway下进行数据库分片操作。
(5)对集合进行分片操作
对集合进行分片操作前,需要为集合user创建索引,具体命令如下:

#切换到数据库school 
mongos> use school
switched to db school
#以"id"作为索引
mongos> db.user.createIndex({"id":1})
{......}

执行上述命令后,我们成功为集合user创建索引。接下来,我们将以索引“id”作为分片键,对集合user进行分片操作,具体命令如下:

#切换到数据库gateway 
mongos> use gateway
#以"id"作为分片键对集合user进行分片
mongos> sh.shardCollection("school.user",{"id":1})
{......}

从上述返回结果“ok:1”可看出,我们成功为数据库school下的集合user开启分片功能。
(6)查看分片信息
在数据库gateway下,执行命令“sh.status()”,查看数据库school中集合user的分片信息。从返回结果可以看出,school.user(即数据库school下的集合user)的分片键(shard key)为id;参数“chunks”中各Shard的分布信息为“shard1 2,shard2 2,shard3 2”,说明shard1、shard2和shard3中分别存在两个chunk。
(7)开启安全认证
MongoDB默认没有开启安全认证,分片集群与副本集开启安全认证的方式基本一致。同样是使用KeyFile安全认证的方式,具体步骤如下。

  1. 创建并同步KeyFile文件;
  2. 创建全局管理用户;
  3. 关闭分片集群;
  4. 修改分片集群中各服务器的配置文件;
  5. 启动分片集群。
#创建并同步KeyFile文件
mkdir -p /opt/servers/mongodb_demo/shardcluster/key
touch /opt/servers/mongodb_demo/shardcluster/key/keyfile
openssl rand -base64 756 -out /opt/servers/mongodb_demo/shardcluster/key/keyfile
chmod 600 /opt/servers/mongodb_demo/shardcluster/key/keyfile
scp -r /opt/servers/mongodb_demo/shardcluster/key user_mongo@nosql2:/opt/servers/mongodb_demo/shardcluster/
#创建全局管理用户
cd /opt/servers/mongodb_demo/shardcluster/mongodb/bin
./mongo --host nosql1 --port 27021
> use admin
> db.createUser({user:"itcastAdmin",pwd:"123456",roles:[{role:"userAdminAnyDatabase",db:"admin"},{role:"readWriteAnyDatabase",db:"admin"},{role:"dbAdminAnyDatabase",db:"admin"}]})
 > use gateway
 #关闭平衡器
 > sh.stopBalancer()
#修改安全认证配置
#在Config Server与Shard启动配置文件中追加
# Config Server配置文件存放目录/opt/servers/mongodb_demo/shardcluster/configServer/configFile
#Shard配置文件存放目录/opt/servers/mongodb_demo/shardcluster/shard/configFile 
keyFile=/opt/servers/mongodb_demo/replicaset/key/keyfile
auth=true
#在mongos启动配置文件中追加
#mongos配置文件目录 /opt/servers/mongodb_demo/shardcluster/mongos/configFile
keyFile=/opt/servers/mongodb_demo/replicaset/key/keyfile
#启动分片集群
cd /opt/servers/mongodb_demo/shardcluster/mongodb/bin
./mongod -f /opt/servers/mongodb_demo/shardcluster/configServer/configFile/mongodb_config.conf

./mongod -f /opt/servers/mongodb_demo/shardcluster/shard/configFile/mongodb_shard1.conf
./mongod -f /opt/servers/mongodb_demo/shardcluster/shard/configFile/mongodb_shard2.conf
./mongod -f /opt/servers/mongodb_demo/shardcluster/shard/configFile/mongodb_shard3.conf

./mongos -f /opt/servers/mongodb_demo/shardcluster/mongos/configFile/mongodb_mongos.conf

(8)验证安全认证
以安全认证模式启动分片集群后,我们通过不指定用户的方式登录mongos的MongoDB客户端,验证是否可以正常读取分片集群中的文档,这里以服务器nosql01为例,具体命令如下:

# 在服务器nosql01中MongoDB的bin目录下执行
$ ./mongo --host nosql01 --port 27021
#需要创建root用户开启平衡器
> use admin
> db.auth("itcastAdmin","123456")
> db.createUser({user:"admin",pwd:"123456",roles:[{role:"root",db:"admin"}]})
> db.auth("admin","123456")
> use gateway
> sh.startBalancer()

执行上述命令后,再依次执行“user school”和“db.user.find().limit(10)”命令,查看集合user中前10条文档,效果具体如下:

mongos> use school
switched to db school
mongos> db.user.find().limit(10)
{......}

从上述返回结果“command find requires authentication”可以看出,查看文档操作需要用户认证后才能查看。
下面,我们以全局用户进行身份验证后,再进行查看文档操作,具体命令如下:

mongos> use admin
switched to db admin
mongos> db.auth("itcastAdmin","123456")
1
mongos> use school
switched to db school> db.user.find().limit(10)
mongos> db.user.find().limit(10)
{......}

从上述返回结果可以看出,客户端成功展示了集合user中的前十条文档内容,因此可以说明我们成功开启分片集群的安全认证。

结尾

制作不易,本人水平不高,希望大家批评指正。