MongoDB构建分片集群及分片管理

一、副本的概念

1.主从复制和副本集区别

主从集群和制本集最大的区别就是副本集没有固定的“主节点";整个集群会选出一个主节点当其挂掉后,又在剩下的从节点中选中其他节点为"主节点"。副本集总有一个活跃点(主primary和一 个或多个备份节点(从secondary)。

2、副本集的两种类型

副本集有两种类型三种角色
两种类型:
主节点(Primary) 类型:数据操作的主要连接点,可读写.
次要(辅助、从)节点(Secondaries) 类型:数据冗余备份节点,可以读或选举。

3、三种角色:

主要成员(Primary) :主要接收所有写操作。就是主节点。
副本成员(Replicate) :从主节点通过复制操作以维护相同的数据集。即备份数据,可写操作,但可以读操作但需要配置。是默认的一种从节点类型。
仲裁者(Arbiter) :不保留任何数据的副本,只具有投票选举作用。当然也可以将仲裁服务器维护为副本集的一部分,即副本成员同时也可以是仲裁者。也是一种从节点类型。

4、缺点

相当于只从复制 master宕机后就凉了 ,为了实现高可用,就不得不介绍一下分片的概念了

二、分片概念

1.数据块

  • 块也叫区间,可能存在一分片一区间和一分片多区间两种情况。
  1. 一分片一区间:数据不会在片之间自动移动来保持分片的数据的均匀性,需要手动拆分分片来移动数据。

  2. 一分片多区间情况:一个数据块默认64MB,当数据块达到64MB时就会创建新的块,当然前提是当前的粒度还允许再拆分,平衡器会保证每个分片数据块的均匀。但是移动块也遵循分片的原则,块之间的数据集不能有交集。
    比如一个块[50-100)现在拆分成两个块,那么默认会拆分成[50-75)[75-100)两个块,如果当前分片块比其它分片的块大于9那么可能[75-100)改块会被移动到新的分片当中。

2.平衡器

平衡器(balancer)负责数据的迁移。它会周期性地检查分片间是否存在不平衡,如果存在,则会开启块的迁移。不平衡的表现指,一个分片明显比其他分片拥有更多的块。假如有一些集合达到了阈值,平衡器则会开始做块迁移。它会从负载比较比较大的分片中选择一个块,并询问该分片是否需要在迁移之前对块进行拆分。完成必要的拆分后,就会将块迁移至数量比较少的机器上。

一、副本的概念
主从复制和副本集区别
主从集群和制本集最大的区别就是副本集没有固定的“主节点";整个集群会选出一个主节点当其挂掉后,又在剩下的从节点中选中其他节点为"主节点"。副本集总有一个活跃点(主primary和一 个或多个备份节点(从secondary)。

1、副本集的两种类型
副本集有两种类型三种角色
两种类型:
主节点(Primary) 类型:数据操作的主要连接点,可读写.
次要(辅助、从)节点(Secondaries) 类型:数据冗余备份节点,可以读或选举。

2、三种角色:
主要成员(Primary) :主要接收所有写操作。就是主节点。
副本成员(Replicate) :从主节点通过复制操作以维护相同的数据集。即备份数据,可写操作,但可以读操作但需要配置。是默认的一种从节点类型。
仲裁者(Arbiter) :不保留任何数据的副本,只具有投票选举作用。当然也可以将仲裁服务器维护为副本集的一部分,即副本成员同时也可以是仲裁者。也是一种从节点类型。
4、缺点
相当于只从复制 master宕机后就凉了 ,为了实现高可用,就不得不介绍一下分片的概念了

三、分片集群包含的组件

MongoDB分片群集包含以下组件: .
●分片(存储)shard:每个分片包含分片数据的子集。 每个分片都可以部署为副本集。
●mongos (路由) : mongos充当查询路由器,在客户端应用程序和分片集群之间提供接口。
●config servers (“调度"的配置) : 配置服务器存储群集的元数据和配置设置。从MongoDB 3.4开始,必须将配置服务器部署为副本集(CSRS)。

在这里插入图片描述

四、构建分片群集

拓扑

在这里插入图片描述

1.解压软件包

[root@localhost ~]# tar zxvf mongodb-linux-x86_64-3.2.1.tgz -C /opt/
[root@localhost ~]# mv /opt/mongodb-linux-x86_64-3.2.1/ /usr/local/mongodb  ##移动到/usr/local下便于管理

2.创建日志文件及数据目录

[root@localhost ~]# mkdir -p /data/mongodb/mongodb{1,2,3,4}
[root@localhost ~]# mkdir /data/mongodb/logs
[root@localhost ~]# touch /data/mongodb/logs/mongodb{1,2,3,4}.1og
[root@localhost ~]# chmod -R 777 /data/mongodb/logs/*.1og     ##一定要授予777权限

3.进行一些缓存优化

[root@localhost ~]# ulimit -n 25000      ##每个进程可以同时打开的最大文件数
[root@localhost ~]# ulimit -u 25000    ##可以运行的最大并发进程数
##### 下面3条优化,当某节点内存不足时,从其他节点分配内存 ########
[root@localhost bin]#  sysctl -w vm.zone_reclaim_mode=0      ##禁止大页面内存的出现
vm.zone_reclaim_mode = 0
[root@localhost bin]#  echo never > /sys/kernel/mm/transparent_hugepage/enabled
[root@localhost bin]#  echo never > /sys/kernel/mm/transparent_hugepage/defrag

4.编写配置文件

[root@localhost ~]# cd /usr/local/mongodb/bin/    ##配置文件就放到/usr/local/mongodb/bin/目录下
[root@localhost bin]#  vim mongodb1.conf
port=37017
dbpath=/data/mongodb/mongodb1
logpath=/data/mongodb/logs/mongodb1.log
logappend=true
fork=true
maxConns=5000
storageEngine=mmapv1
configsvr=true         ##指定这是属于配置服务器的模式

5.建立软连接,便于调用命令

[root@localhost bin]# ln -s /usr/local/mongodb/bin/mongod /usr/bin/mongod
[root@localhost bin]# ln -s /usr/local/mongodb/bin/mongo /usr/bin/mongo

6.启动实例

[root@localhost bin]# mongod -f /usr/local/mongodb/bin/mongodb1.conf
about to fork child process, waiting until server is ready for connections.
forked process: 2099
child process started successfully, parent exiting

7.配置分片服务器

[root@localhost bin]# cp -p mongodb1.conf mongodb2.conf
[root@localhost bin]# vim mongodb2.conf
port=47017    ##修改端口号
dbpath=/data/mongodb/mongodb2     ##修改数据目录位置
logpath=/data/mongodb/logs/mongodb2.log    ##修改日志文件路径
shardsvr=true    ##configsvr改成shardsvr

[root@localhost bin]# cp -p mongodb2.conf mongodb3.conf
[root@localhost bin]# vim mongodb3.conf 
port=47018    ##修改端口号
dbpath=/data/mongodb/mongodb3     ##修改数据目录位置
logpath=/data/mongodb/logs/mongodb3.log    ##修改日志文件路径

[root@localhost bin]# cp -p mongodb2.conf mongodb4.conf
[root@localhost bin]# vim mongodb4.conf 
port=47019    ##修改端口号
dbpath=/data/mongodb/mongodb4     ##修改数据目录位置
logpath=/data/mongodb/logs/mongodb4.log    ##修改日志文件路径
#######################依次启动实例####################################
[root@localhost bin]# mongod -f /usr/local/mongodb/bin/mongodb2.conf     ##'启动实例2'
about to fork child process, waiting until server is ready for connections.
forked process: 2393
child process started successfully, parent exiting
[root@localhost bin]# mongod -f /usr/local/mongodb/bin/mongodb3.conf    ##'启动实例3'
about to fork child process, waiting until server is ready for connections.
forked process: 2408
child process started successfully, parent exiting
[root@localhost bin]# mongod -f /usr/local/mongodb/bin/mongodb4.conf    ##'启动实例4'
about to fork child process, waiting until server is ready for connections.
forked process: 2423
child process started successfully, parent exiting

8.启动路由服务器

[root@localhost bin]# ./mongos --help    ##mongos是开启路由模式的一个脚本,--help查看帮助信息
[root@localhost bin]# ./mongos --port 27017 --fork --logpath=/usr/local/mongodb/bin/route.log --configdb 192.168.10.10:37017 --chunkSize 1   
##--port指定对方访问端口(入口),--fork后台运行;--logpath日志文件位置;--configdb指定处理请求的配置服务器;--chunkSize指定数据块(最后这个配置只是用来测试的,不加也行,默认空间是200M大小)
2020-11-09T01:36:31.297+0800 W SHARDING [main] Running a sharded cluster with fewer than 3 config servers should only be done for testing purposes and is not recommended for production.
about to fork child process, waiting until server is ready for connections.
forked process: 37738
child process started successfully, parent exiting

[root@localhost bin]# mongo     ##mongo命令直接进入路由服务器(默认端口是27017
MongoDB shell version: 3.2.1
connecting to: test
Server has startup warnings: 
2020-11-09T01:36:31.307+0800 I CONTROL  [main] ** WARNING: You are running this process as the root user, which is not recommended.
2020-11-09T01:36:31.307+0800 I CONTROL  [main] 
mongos> 

9.启用分片服务器

sh.addShard()命令添加分片服务器

[root@localhost bin]# mongo     ##进入路由服务器实际上相当于进入了配置服务器
mongos> show dbs       ##只能查看到一个配置config库
config  0.031GB
mongos> sh.status()     ##查看该服务器下是否有分片服务器
--- Sharding Status --- 
  sharding version: {
	"_id" : 1,
	"minCompatibleVersion" : 5,
	"currentVersion" : 6,
	"clusterId" : ObjectId("5fa82c9fef682337a84b13a1")
}
  shards:       ##现在这个版块下是空的,说明并没有分片服务器
  active mongoses:
	"3.2.1" : 1
  balancer:
	Currently enabled:  yes
	Currently running:  no
	Failed balancer rounds in last 5 attempts:  0
	Migration Results for the last 24 hours: 
		No recent migrations
  databases:
mongos> sh.addShard("192.168.10.10:47017")      ##添加分片服务器192.168.10.10:47017
{ "shardAdded" : "shard0000", "ok" : 1 }
mongos> sh.addShard("192.168.10.10:47018")      ##添加分片服务器192.168.10.10:47018
{ "shardAdded" : "shard0001", "ok" : 1 }

mongos> sh.status()       ##再次查看分片集群状态
--- Sharding Status --- 
  sharding version: {
	"_id" : 1,
	"minCompatibleVersion" : 5,
	"currentVersion" : 6,
	"clusterId" : ObjectId("5fa82c9fef682337a84b13a1")
}
  shards:                ##在shards下多次两个节点
	{  "_id" : "shard0000",  "host" : "192.168.10.10:47017" }
	{  "_id" : "shard0001",  "host" : "192.168.10.10:47018" }
  active mongoses:
	"3.2.1" : 1
  balancer:

10 分片功能管理初步了解

mongos> use school     ##进入school库
 
mongos> for(var i=1;i<=10000;i++)db.info.insert({"id":i,"team":"member"+i})    ##插入10000条数据,用于验证分片
 
mongos> db.info.find().limit(3)     ##查看头3行数据
{ "_id" : ObjectId("5fa83a28597e4c3f6bb3f3c6"), "id" : 1, "team" : "member1" }
{ "_id" : ObjectId("5fa83a29597e4c3f6bb3f3c7"), "id" : 2, "team" : "member2" }
{ "_id" : ObjectId("5fa83a29597e4c3f6bb3f3c8"), "id" : 3, "team" : "member3" }


############# 也可以通过在MongoDB外用文件导入数据######################
./mongoimport -d school -c info --file /opt/test.txt
#################################################################

mongos> show dbs    ##插入数据后新建了一个school库
config  0.031GB
school  0.078GB
mongos> use school   ##进入school库
 
mongos> show collections    ##查看集合,已经有数据了
info
system.indexes

mongos> sh.status()
……省略部分
  databases:
	{  "_id" : "school",  "primary" : "shard0000",  "partitioned" : false }   ##数据并没有进行分片,提示false


mongos> sh.enableSharding("school")    ##对school库开启分片处理

mongos> sh.status()
……省略部分
  databases:
	{  "_id" : "school",  "primary" : "shard0000",  "partitioned" : true }   ##显示ture,开启了分片处理,但是到这一步只是开启了对库的分片,对集合并没有分片



#对集合进行分片需要先创建索引
mongos> db.info.createIndex({"id":1})     ##给info集合创建以“id”为索引,从1开始

mongos> sh.shardCollection("school.info",{"id":1})     ##对集合info分片


mongos> sh.status()    ##再次查看信息,可以看出10000条数据分成了三段1~4682,4682~9364,9364~最后
……省略部分
  databases:
	{  "_id" : "school",  "primary" : "shard0000",  "partitioned" : true }
		school.info
			shard key: { "id" : 1 }
			unique: false
			balancing: true
			chunks:
				shard0000	3
			{ "id" : { "$minKey" : 1 } } -->> { "id" : 4682 } on : shard0000 Timestamp(1, 0) 
			{ "id" : 4682 } -->> { "id" : 9364 } on : shard0000 Timestamp(1, 1) 
			{ "id" : 9364 } -->> { "id" : { "$maxKey" : 1 } } on : shard0000 Timestamp(1, 2) 

总结:一共三个步骤,1.配置路由服务器,2.构建配置服务器,3.构建分片服务器

五、分片管理示例

集合分片

mongos> use school

mongos> sh.enableSharding("school")       ##开启school库的分片功能

mongos> for(var i=1;i<=50000;i++)db.test.insert({"id":i,"name":"test"+i})     ##插入50000条数据

mongos> show tables    ##查看集合
info
system.indexes
test

mongos> db.test.count()      ##统计有5000条记录
50000

mongos> db.test.find().limit(3)       ##查看开头三条数据,数据插入成功
{ "_id" : ObjectId("5fa8483f3a9549125843e1f8"), "id" : 1, "name" : "test1" }
{ "_id" : ObjectId("5fa8483f3a9549125843e1f9"), "id" : 2, "name" : "test2" }
{ "_id" : ObjectId("5fa8483f3a9549125843e1fa"), "id" : 3, "name" : "test3" }

mongos> db.test.createIndex({"id":1})   ##建立索引,以"id"为索引,从1开始

mongos> sh.shardCollection("school.test",{"id":1})       ##根据索引对test集合进行分片,索引建议最好是能作为主键的字段(非空且唯一),例如像性别这样的键就不适合做索引,除了男就是女两种值。

mongos> sh.status()         ##查看分片信息
--- Sharding Status --- 
……省略部分
  shards:
  	{  "_id" : "shard0000",  "host" : "192.168.10.10:47017" }       ##192.168.10.10:47017节点的id号是shard0000
	{  "_id" : "shard0001",  "host" : "192.168.10.10:47018" }        ##192.168.10.10:47018节点的id号是shard0001

  databases:
	{  "_id" : "school",  "primary" : "shard0000",  "partitioned" : true }
		school.info                                      ##info集合的分片信息
			shard key: { "id" : 1 }
			unique: false
			balancing: true
			chunks:
				shard0000	3
				shard0001	2
			{ "id" : { "$minKey" : 1 } } -->> { "id" : 4682 } on : shard0001 Timestamp(2, 0) 
			{ "id" : 4682 } -->> { "id" : 9364 } on : shard0000 Timestamp(3, 1) 
			{ "id" : 9364 } -->> { "id" : 13407 } on : shard0000 Timestamp(2, 2) 
			{ "id" : 13407 } -->> { "id" : 18945 } on : shard0000 Timestamp(2, 3) 
			{ "id" : 18945 } -->> { "id" : { "$maxKey" : 1 } } on : shard0001 Timestamp(3, 0) 
		school.test                                      ##test集合的分片信息
			shard key: { "id" : 1 }
			unique: false
			balancing: true
			chunks:
				shard0000	6               ##6段分片放在节点00
				shard0001	5                 ##5段分片放在节点01
			{ "id" : { "$minKey" : 1 } } -->> { "id" : 4682 } on : shard0001 Timestamp(2, 0)      ##这段分片放在shard01节点上
			{ "id" : 4682 } -->> { "id" : 9364 } on : shard0001 Timestamp(3, 0)                        ##这段分片也是放在shard01节点上
			{ "id" : 9364 } -->> { "id" : 14046 } on : shard0001 Timestamp(4, 0) 
			{ "id" : 14046 } -->> { "id" : 18728 } on : shard0001 Timestamp(5, 0) 
			{ "id" : 18728 } -->> { "id" : 23410 } on : shard0001 Timestamp(6, 0) 
			{ "id" : 23410 } -->> { "id" : 28092 } on : shard0000 Timestamp(6, 1)                  ##这段分片放在shard00节点上
			{ "id" : 28092 } -->> { "id" : 32774 } on : shard0000 Timestamp(1, 6) 
			{ "id" : 32774 } -->> { "id" : 37456 } on : shard0000 Timestamp(1, 7) 
			{ "id" : 37456 } -->> { "id" : 42138 } on : shard0000 Timestamp(1, 8) 
			{ "id" : 42138 } -->> { "id" : 46820 } on : shard0000 Timestamp(1, 9) 
			{ "id" : 46820 } -->> { "id" : { "$maxKey" : 1 } } on : shard0000 Timestamp(1, 10) 

添加标签

mongos> sh.addShardTag("shard0000","slave1")    ##shard0000是节点id号,通过sh.status()可以查到,设置给节点标签slave1
mongos> sh.addShardTag("shard0001","slave2")   ##给shard0001节点打上标签salve2
mongos> sh.status()      ##查看分片信息
--- Sharding Status --- 
  sharding version: {
	"_id" : 1,
	"minCompatibleVersion" : 5,
	"currentVersion" : 6,
	"clusterId" : ObjectId("5fa82c9fef682337a84b13a1")
}
  shards:
	{  "_id" : "shard0000",  "host" : "192.168.10.10:47017",  "tags" : [ "slave1" ] }    ##后面追加了标签信息
	{  "_id" : "shard0001",  "host" : "192.168.10.10:47018",  "tags" : [ "slave2" ] }
……省略部分

添加新节点,查看数据分片情况

注意点:我们所有的操作都通过路由服务器请求配置服务器,有配置服务器完成的
[root@localhost ~]# mongo --port 37017     ##进入配置服务器 
configsvr> use config     ##进入config库
switched to db config
configsvr> show tables      ##可看到这几个集合,我们所有的信息都可以在这些集合中看到
……省略部分
chunks       ##分片数据块信息
collections    ##集合信息
databases    ##数据库信息
……省略部分

configsvr> db.databases.find()       ##可以查看到我们新建的数据库
{ "_id" : "school", "primary" : "shard0000", "partitioned" : true }

configsvr> db.collections.find()    ##可以查看集合信息

configsvr> db.databases.find()   ##可以查看分片(数据块)信息



[root@localhost ~]# mongo    ##进入路由服务器

mongos> sh.addShard("192.168.10.10:47019")       ##再次添加一个分片服务器(上个实验中创建好了的实例)

mongos> sh.status()       ##查看分片信息
-……省略部分
  shards:          ###添加分片节点后,自动更新信息,可以看到多出了一个分片节点
	{  "_id" : "shard0000",  "host" : "192.168.10.10:47017",  "tags" : [ "slave1" ] }
	{  "_id" : "shard0001",  "host" : "192.168.10.10:47018",  "tags" : [ "slave2" ] }
	{  "_id" : "shard0002",  "host" : "192.168.10.10:47019" }
  ……省略部分
  databases:                              ##由下面信息可以看出,分片数据段重新进行了分配,新加的节点与旧节点之间平均分配旧数据
	{  "_id" : "school",  "primary" : "shard0000",  "partitioned" : true }
		…………省略部分
		school.test
			shard key: { "id" : 1 }
			unique: false
			balancing: true
			chunks:
				shard0000	4
				shard0001	4
				shard0002	3
			{ "id" : { "$minKey" : 1 } } -->> { "id" : 4682 } on : shard0002 Timestamp(9, 0) 
			{ "id" : 4682 } -->> { "id" : 9364 } on : shard0001 Timestamp(9, 1) 
			{ "id" : 9364 } -->> { "id" : 14046 } on : shard0001 Timestamp(4, 0) 
			{ "id" : 14046 } -->> { "id" : 18728 } on : shard0001 Timestamp(5, 0) 
			{ "id" : 18728 } -->> { "id" : 23410 } on : shard0001 Timestamp(6, 0) 
			{ "id" : 23410 } -->> { "id" : 28092 } on : shard0002 Timestamp(7, 0) 
			{ "id" : 28092 } -->> { "id" : 32774 } on : shard0002 Timestamp(8, 0) 
			{ "id" : 32774 } -->> { "id" : 37456 } on : shard0000 Timestamp(8, 1) 
			{ "id" : 37456 } -->> { "id" : 42138 } on : shard0000 Timestamp(1, 8) 
			{ "id" : 42138 } -->> { "id" : 46820 } on : shard0000 Timestamp(1, 9) 
			{ "id" : 46820 } -->> { "id" : { "$maxKey" : 1 } } on : shard0000 Timestamp(1, 10) 

删除分片节点

mongos> use admin       ###需要先进admin库

mongos> db.runCommand({"removeshard":"192.168.10.10:47019"})     ##删除分片节点

mongos> sh.status()
--- Sharding Status --- 
 ……省略部分
  shards:
	{  "_id" : "shard0000",  "host" : "192.168.10.10:47017",  "tags" : [ "slave1" ] }
	{  "_id" : "shard0001",  "host" : "192.168.10.10:47018",  "tags" : [ "slave2" ] }
	{  "_id" : "shard0002",  "host" : "192.168.10.10:47019",  "draining" : true }      ##显示这台节点停机
 ……省略部分
  databases:                                ##由下面信息可以看出,删除后,数据再次从新分配给存活的两台节点
	{  "_id" : "school",  "primary" : "shard0000",  "partitioned" : true }
		school.test
			shard key: { "id" : 1 }
			unique: false
			balancing: true
			chunks:
				shard0000	6
				shard0001	5
			{ "id" : { "$minKey" : 1 } } -->> { "id" : 4682 } on : shard0000 Timestamp(10, 0) 
			{ "id" : 4682 } -->> { "id" : 9364 } on : shard0001 Timestamp(9, 1) 
			{ "id" : 9364 } -->> { "id" : 14046 } on : shard0001 Timestamp(4, 0) 
			{ "id" : 14046 } -->> { "id" : 18728 } on : shard0001 Timestamp(5, 0) 
			{ "id" : 18728 } -->> { "id" : 23410 } on : shard0001 Timestamp(6, 0) 
			{ "id" : 23410 } -->> { "id" : 28092 } on : shard0001 Timestamp(11, 0) 
			{ "id" : 28092 } -->> { "id" : 32774 } on : shard0000 Timestamp(12, 0) 
			{ "id" : 32774 } -->> { "id" : 37456 } on : shard0000 Timestamp(8, 1) 
			{ "id" : 37456 } -->> { "id" : 42138 } on : shard0000 Timestamp(1, 8) 
			{ "id" : 42138 } -->> { "id" : 46820 } on : shard0000 Timestamp(1, 9) 
			{ "id" : 46820 } -->> { "id" : { "$maxKey" : 1 } } on : shard0000 Timestamp(1, 10) 

总结:由此可以看出,MongoDB数据库非常灵活,无论删除或者添加分片节点,数据自动进行划分,十分有利于服务器的横向扩展,因此在大数据处理上非常受欢迎

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值