- 一、副本的概念
- 1.主从复制和副本集区别
- 2、副本集的两种类型
- 3、三种角色:
- 4、缺点
- 二、分片概念
- 1.数据块
- 2.平衡器
- 三、分片集群包含的组件
- 四、构建分片群集
- 拓扑
- 1.解压软件包
- 2.创建日志文件及数据目录
- 3.进行一些缓存优化
- 4.编写配置文件
- 5.建立软连接,便于调用命令
- 6.启动实例
- 7.配置分片服务器
- 8.启动路由服务器
- 9.启用分片服务器
- 10 分片功能管理初步了解
- 五、分片管理示例
一、副本的概念
1.主从复制和副本集区别
主从集群和制本集最大的区别就是副本集没有固定的“主节点";整个集群会选出一个主节点当其挂掉后,又在剩下的从节点中选中其他节点为"主节点"。副本集总有一个活跃点(主primary和一 个或多个备份节点(从secondary)。
2、副本集的两种类型
副本集有两种类型三种角色
两种类型:
主节点(Primary) 类型:数据操作的主要连接点,可读写.
次要(辅助、从)节点(Secondaries) 类型:数据冗余备份节点,可以读或选举。
3、三种角色:
主要成员(Primary) :主要接收所有写操作。就是主节点。
副本成员(Replicate) :从主节点通过复制操作以维护相同的数据集。即备份数据,可写操作,但可以读操作但需要配置。是默认的一种从节点类型。
仲裁者(Arbiter) :不保留任何数据的副本,只具有投票选举作用。当然也可以将仲裁服务器维护为副本集的一部分,即副本成员同时也可以是仲裁者。也是一种从节点类型。
4、缺点
相当于只从复制 master宕机后就凉了 ,为了实现高可用,就不得不介绍一下分片的概念了
二、分片概念
1.数据块
- 块也叫区间,可能存在一分片一区间和一分片多区间两种情况。
一分片一区间:数据不会在片之间自动移动来保持分片的数据的均匀性,需要手动拆分分片来移动数据。
一分片多区间情况:一个数据块默认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数据库非常灵活,无论删除或者添加分片节点,数据自动进行划分,十分有利于服务器的横向扩展,因此在大数据处理上非常受欢迎