C/C++Linux服务器开发/后台架构师知识体系整理

分片(sharding)是 MongoDB 用来将大型集合分割到不同服务器(或者说一个集群)上所采用的方法。尽管分片起源于关系型数据库分区,但 MongoDB 分片完全又是另一回事。

和 MySQL 分区方案相比,MongoDB 的最大区别在于它几乎能自动完成所有事情,只要告诉 MongoDB 要分配数据,它就能自动维护数据在不同服务器之间的均衡。

1. MongoDB分片介绍

1.1 分片的目的

高数据量和吞吐量的数据库应用会对单机的性能造成较大压力,大的查询量会将单机的CPU耗尽,大的数据量对单机的存储压力较大,最终会耗尽系统的内存而将压力转移到磁盘IO上。

为了解决这些问题,有两个基本的方法: 垂直扩展和水平扩展。

垂直扩展:增加更多的CPU和存储资源来扩展容量。

水平扩展:将数据集分布在多个服务器上。水平扩展即分片。

1.2 分片设计思想

分片为应对高吞吐量与大数据量提供了方法。使用分片减少了每个分片需要处理的请求数,因此,通过水平扩展,集群可以提高自己的存储容量和吞吐量。举例来说,当插入一条数据时,应用只需要访问存储这条数据的分片。

使用分片减少了每个分片存储的数据。

例如,如果数据库1tb的数据集,并有4个分片,然后每个分片可能仅持有256 GB的数据。如果有40个分片,那么每个切分可能只有25GB的数据。

1.3 分片机制提供了如下三种优势

1.对集群进行抽象,让集群“不可见”

MongoDB自带了一个叫做mongos的专有路由进程。mongos就是掌握统一路口的路由器,其会将客户端发来的请求准确无误的路由到集群中的一个或者一组服务器上,同时会把接收到的响应拼装起来发回到客户端。

2.保证集群总是可读写

MongoDB通过多种途径来确保集群的可用性和可靠性。将MongoDB的分片和复制功能结合使用,在确保数据分片到多台服务器的同时,也确保了每分数据都有相应的备份,这样就可以确保有服务器换掉时,其他的从库可以立即接替坏掉的部分继续工作。

3.使集群易于扩展

当系统需要更多的空间和资源的时候,MongoDB使我们可以按需方便的扩充系统容量。

1.4 分片集群架构



分片集群的构造

(1)mongos :数据路由,和客户端打交道的模块。mongos本身没有任何数据,他也不知道该怎么处理这数据,去找config server

(2)config server:所有存、取数据的方式,所有shard节点的信息,分片功能的一些配置信息。可以理解为真实数据的元数据。

(3)shard:真正的数据存储位置,以chunk为单位存数据。

Mongos本身并不持久化数据,Sharded cluster所有的元数据都会存储到Config Server,而用户的数据会议分散存储到各个shard。Mongos启动后,会从配置服务器加载元数据,开始提供服务,将用户的请求正确路由到对应的碎片。

Mongos的路由功能

当数据写入时,MongoDB Cluster根据分片键设计写入数据。

当外部语句发起数据查询时,MongoDB根据数据分布自动路由至指定节点返回数据。

2. 集群中数据分布

2.1 Chunk是什么

在一个shard server内部,MongoDB还是会把数据分为chunks,每个chunk代表这个shard server内部一部分数据。chunk的产生,会有以下两个用途:

Splitting:当一个chunk的大小超过配置中的chunk size时,MongoDB的后台进程会把这个chunk切分成更小的chunk,从而避免chunk过大的情况

Balancing:在MongoDB中,balancer是一个后台进程,负责chunk的迁移,从而均衡各个shard server的负载,系统初始1个chunk,chunk size默认值64M,生产库上选择适合业务的chunk size是最好的。ongoDB会自动拆分和迁移chunks。

分片集群的数据分布(shard节点)

(1)使用chunk来存储数据

(2)进群搭建完成之后,默认开启一个chunk,大小是64M,

(3)存储需求超过64M,chunk会进行分裂,如果单位时间存储需求很大,设置更大的chunk

(4)chunk会被自动均衡迁移。

2.2 chunksize 的选择

适合业务的chunksize是最好的。

chunk的分裂和迁移非常消耗IO资源;chunk分裂的时机:在插入和更新,读数据不会分裂。

chunksize的选择:

小的chunksize:数据均衡是迁移速度快,数据分布更均匀。数据分裂频繁,路由节点消耗更多资源。大的chunksize:数据分裂少。数据块移动集中消耗IO资源。通常100-200M

2.3 chunk分裂及迁移

随着数据的增长,其中的数据大小超过了配置的chunk size,默认是64M,则这个chunk就会分裂成两个。数据的增长会让chunk分裂得越来越多。
这时候,各个shard 上的chunk数量就会不平衡。这时候,mongos中的一个组件balancer 就会执行自动平衡。把chunk从chunk数量最多的shard节点挪动到数量最少的节点。

chunkSize 对分裂及迁移的影响

MongoDB 默认的 chunkSize 为64MB,如无特殊需求,建议保持默认值;chunkSize 会直接影响到 chunk 分裂、迁移的行为。

chunkSize 越小,chunk 分裂及迁移越多,数据分布越均衡;反之,chunkSize 越大,chunk 分裂及迁移会更少,但可能导致数据分布不均。

chunkSize 太小,容易出现 jumbo chunk(即shardKey 的某个取值出现频率很高,这些文档只能放到一个 chunk 里,无法再分裂)而无法迁移;chunkSize 越大,则可能出现 chunk 内文档数太多(chunk 内文档数不能超过 250000 )而无法迁移。

chunk 自动分裂只会在数据写入时触发,所以如果将 chunkSize 改小,系统需要一定的时间来将 chunk 分裂到指定的大小。

chunk 只会分裂,不会合并,所以即使将 chunkSize 改大,现有的 chunk 数量不会减少,但 chunk 大小会随着写入不断增长,直到达到目标大小。

3. 数据区分

3.1 分片键shard key

MongoDB 中数据的分片是、以集合为基本单位的,集合中的数据通过片键(Shard key)被分成多部分。其实片键就是在集合中选一个键,用该键的值作为数据拆分的依据。

所以一个好的片键对分片至关重要。片键必须是一个索引,通过sh.shardCollection加会自动创建索引(前提是此集合不存在的情况下)。一个自增的片键对写入和数据均匀分布就不是很好,因为自增的片键总会在一个分片上写入,后续达到某个阀值可能会写到别的分片。但是按照片键查询会非常高效。

随机片键对数据的均匀分布效果很好。注意尽量避免在多个分片上进行查询。在所有分片上查询,mongos会对结果进行归并排序。

对集合进行分片时,你需要选择一个片键,片键是每条记录都必须包含的,且建立了索引的单个字段或复合字段,MongoDB按照片键将数据划分到不同的数据块中,并将数据块均衡地分布到所有分片中。

为了按照片键划分数据块,MongoDB使用基于范围的分片方式或者 基于哈希的分片方式。

注意:

分片键是不可变。

分片键必须有索引。

分片键大小限制512bytes。

分片键用于路由查询。

MongoDB不接受已进行collection级分片的collection上插入无分片

键的文档(也不支持空值插入)

3.2 以范围为基础的分片Sharded Cluster

Sharded Cluster支持将单个集合的数据分散存储在多shard上,用户可以指定根据集合内文档的某个字段即shard key来进行范围分片(range sharding)。

对于基于范围的分片,MongoDB按照片键的范围把数据分成不同部分。

假设有一个数字的片键:想象一个从负无穷到正无穷的直线,每一个片键的值都在直线上画了一个点。MongoDB把这条直线划分为更短的不重叠的片段,并称之为数据块,每个数据块包含了片键在一定范围内的数据。在使用片键做范围划分的系统中,拥有”相近”片键的文档很可能存储在同一个数据块中,因此也会存储在同一个分片中。

3.3 基于哈希的分片

分片过程中利用哈希索引作为分片的单个键,且哈希分片的片键只能使用一个字段,而基于哈希片键最大的好处就是保证数据在各个节点分布基本均匀。

对于基于哈希的分片,MongoDB计算一个字段的哈希值,并用这个哈希值来创建数据块。在使用基于哈希分片的系统中,拥有”相近”片键的文档很可能不会存储在同一个数据块中,因此数据的分离性更好一些。

Hash分片与范围分片互补,能将文档随机的分散到各个chunk,充分的扩展写能力,弥补了范围分片的不足,但不能高效的服务范围查询,所有的范围查询要分发到后端所有的Shard才能找出满足条件的文档。

3.4 分片键选择建议

1、递增的sharding key

数据文件挪动小。(优势)

因为数据文件递增,所以会把insert的写IO永久放在最后一片上,造成最后一片的写热点。同时,随着最后一片的数据量增大,将不断的发生迁移至之前的片上。

2、随机的sharding key

数据分布均匀,insert的写IO均匀分布在多个片上。(优势)

大量的随机IO,磁盘不堪重荷。

3、混合型key

大方向随机递增,小范围随机分布。

为了防止出现大量的chunk均衡迁移,可能造成的IO压力。我们需要设置合理分片使用策略(片键的选择、分片算法(range、hash))

分片注意:

分片键是不可变、分片键必须有索引、分片键大小限制512bytes、分片键用于路由查询。

MongoDB不接受已进行collection级分片的collection上插入无分片键的文档(也不支持空值插入)

4. 部署分片集群

4.1 环境准备

创建程序所需的目录

for  i in 17 18 19 20 21 22 23 24 25 26 do mkdir -p /mongodb/280$i/conf  mkdir -p /mongodb/280$i/data  mkdir -p /mongodb/280$i/log
done

4.2 shard集群配置

编辑shard集群配置文件

cat > /mongodb/28021/conf/mongod.conf <<'EOF'
systemLog:destination: filepath: /mongodb/28021/log/mongodb.log   logAppend: true
storage:journal:enabled: truedbPath: /mongodb/28021/datadirectoryPerDB: true#engine: wiredTigerwiredTiger:engineConfig:cacheSizeGB: 1directoryForIndexes: truecollectionConfig:blockCompressor: zlibindexConfig:prefixCompression: true
net:bindIp: 10.0.0.152port: 28021
replication:oplogSizeMB: 2048replSetName: sh1
sharding:clusterRole: shardsvr
processManagement: fork: true
EOF

复制shard集群配置文件

for  i in  22 23 24 25 26  do  \cp  /mongodb/28021/conf/mongod.conf  /mongodb/280$i/conf/
done

修改配置文件端口

for  i in   22 23 24 25 26  do sed  -i  "s#28021#280$i#g" /mongodb/280$i/conf/mongod.conf
done

修改配置文件复制集名称(replSetName)

for  i in    24 25 26  do sed  -i  "s#sh1#sh2#g" /mongodb/280$i/conf/mongod.conf
done

启动shard集群

for  i in  21 22 23 24 25 26do  mongod -f /mongodb/280$i/conf/mongod.conf
done

配置复制集1

mongo --host 10.0.0.152 --port 28021  admin

# 配置复制集

config = {_id: 'sh1', members: [{_id: 0, host: '10.0.0.152:28021'},{_id: 1, host: '10.0.0.152:28022'},{_id: 2, host: '10.0.0.152:28023',"arbiterOnly":true}]}  # 初始化配置
rs.initiate(config)

配置复制集2

mongo --host 10.0.0.152 --port 28024  admin

# 配置复制集

config = {_id: 'sh2', members: [{_id: 0, host: '10.0.0.152:28024'},{_id: 1, host: '10.0.0.152:28025'},{_id: 2, host: '10.0.0.152:28026',"arbiterOnly":true}]}
# 初始化配置
rs.initiate(config)

4.3 config集群配置

创建主节点配置文件

cat > /mongodb/28018/conf/mongod.conf <<'EOF'
systemLog:destination: filepath: /mongodb/28018/log/mongodb.conflogAppend: true
storage:journal:enabled: truedbPath: /mongodb/28018/datadirectoryPerDB: true#engine: wiredTigerwiredTiger:engineConfig:cacheSizeGB: 1directoryForIndexes: truecollectionConfig:blockCompressor: zlibindexConfig:prefixCompression: true
net:bindIp: 10.0.0.152port: 28018
replication:oplogSizeMB: 2048replSetName: configReplSet
sharding:clusterRole: configsvr
processManagement: fork: true
EOF

将配置文件分发到从节点

for  i in 19 20 do  \cp  /mongodb/28018/conf/mongod.conf  /mongodb/280$i/conf/
done

修改配置文件端口信息

for  i in 19 20  do sed  -i  "s#28018#280$i#g" /mongodb/280$i/conf/mongod.conf
done

启动config server集群

for  i in  18 19 20 do  mongod -f /mongodb/280$i/conf/mongod.conf
done

配置config server复制集

mongo --host 10.0.0.152 --port 28018  admin

# 配置复制集信息

config = {_id: 'configReplSet', members: [{_id: 0, host: '10.0.0.152:28018'},{_id: 1, host: '10.0.0.152:28019'},{_id: 2, host: '10.0.0.152:28020'}]}
# 初始化配置
rs.initiate(config)

注:config server 使用复制集不用有arbiter节点。3.4版本以后config必须为复制集

4.4 mongos节点配置

修改配置文件

cat > /mongodb/28017/conf/mongos.conf <<'EOF'
systemLog:destination: filepath: /mongodb/28017/log/mongos.loglogAppend: true
net:bindIp: 10.0.0.152port: 28017
sharding:configDB: configReplSet/10.0.0.152:28108,10.0.0.152:28019,10.0.0.152:28020
processManagement: fork: true
EOF

启动mongos

mongos -f /mongodb/28017/conf/mongos.conf

登陆到mongos

mongo 10.0.0.152:28017/admin

添加分片节点

db.runCommand( { addshard : "sh1/10.0.0.152:28021,10.0.0.152:28022,10.0.0.152:28023",name:"shard1"} )
db.runCommand( { addshard : "sh2/10.0.0.152:28024,10.0.0.152:28025,10.0.0.152:28026",name:"shard2"} )

列出分片

mongos> db.runCommand( { listshards : 1 } )
{"shards" : [{"_id" : "shard2","host" : "sh2/10.0.0.152:28024,10.0.0.152:28025"},{"_id" : "shard1","host" : "sh1/10.0.0.152:28021,10.0.0.152:28022"}],"ok" : 1
}

整体状态查看

mongos> sh.status();

至此MongoDB的分片集群就搭建完成。

4.5 数据库分片配置

激活数据库分片功能

语法:( { enablesharding : "数据库名称" } )mongos> db.runCommand( { enablesharding : "test" } )

指定分片建对集合分片,范围片键–创建索引

mongos> use test
mongos> db.vast.ensureIndex( { id: 1 } )
mongos> use admin
mongos> db.runCommand( { shardcollection : "test.vast",key : {id: 1} } )

集合分片验证

mongos> use test
mongos> for(i=0;i<20000;i++){ db.vast1.insert({"id":i,"name":"clsn","age":70,"date":new Date()}); }
mongos> db.vast.stats()

插入数据的条数尽量大些,能够看出更好的效果。

5. 分片集群的操作

5.1 不同分片键的配置

范围片键

admin> sh.shardCollection("数据库名称.集合名称",key : {分片键: 1}  )
或
admin> db.runCommand( { shardcollection : "数据库名称.集合名称",key : {分片键: 1} } )

eg:

admin > sh.shardCollection("test.vast",key : {id: 1}  )
或
admin> db.runCommand( { shardcollection : "test.vast",key : {id: 1} } )

哈希片键

admin > sh.shardCollection( "数据库名.集合名", { 片键: "hashed" } )

创建哈希索引

admin> db.vast.ensureIndex( { a: "hashed" } )
admin > sh.shardCollection( "test.vast", { a: "hashed" } )

5.2 分片集群的操作

判断是否Shard集群

admin> db.runCommand({ isdbgrid : 1})

列出所有分片信息

admin> db.runCommand({ listshards : 1})

列出开启分片的数据库

admin> use config
config> db.databases.find( { "partitioned": true } )
config> db.databases.find() //列出所有数据库分片情况

查看分片的片键

config> db.collections.find()
{"_id" : "test.vast","lastmodEpoch" : ObjectId("58a599f19c898bbfb818b63c"),"lastmod" : ISODate("1970-02-19T17:02:47.296Z"),"dropped" : false,"key" : {"id" : 1},"unique" : false
}

查看分片的详细信息

admin> db.printShardingStatus()
或
admin> sh.status()

删除分片节点

sh.getBalancerState()
mongos> db.runCommand( { removeShard: "shard2" } )

6. balance操作

查看mongo集群是否开启了 balance 状态

mongos> sh.getBalancerState()
true

当然你也可以通过在路由节点mongos上执行sh.status() 查看balance状态。

如果balance开启,查看是否正在有数据的迁移

连接mongo集群的路由节点

mongos> sh.isBalancerRunning()
false

6.1 设置balance 窗口

(1)连接mongo集群的路由节点

(2)切换到配置节点

     use config

(3)确定balance 开启中

 sh.getBalancerState()

如果未开启,执行命令

   sh.setBalancerState( true )

(4)修改balance 窗口的时间

db.settings.update({ _id: "balancer" },{ $set: { activeWindow : { start : "<start-time>", stop : "<stop-time>" } } },{ upsert: true }
)

eg:

db.settings.update({ _id : "balancer" }, { $set : { activeWindow : { start : "00:00", stop : "5:00" } } }, true )当你设置了activeWindow,就不能用sh.startBalancer() 启动balance

NOTE
The balancer window must be sufficient to complete the migration of all data inserted during the day.
As data insert rates can change based on activity and usage patterns, it is important to ensure that the balancing window you select will be sufficient to support the needs of your deployment.

(5)删除balance 窗口

use config
db.settings.update({ _id : "balancer" }, { $unset : { activeWindow : true } })

6.2 关闭balance

默认balance 的运行可以在任何时间,只迁移需要迁移的chunk,如果要关闭balance运行,停止一段时间可以用下列方法:

(1) 连接到路由mongos节点

(2) 停止balance

  sh.stopBalancer()

(3) 查看balance状态

  sh.getBalancerState()

(4)停止balance 后,没有迁移进程正在迁移,可以执行下列命令

use config
while( sh.isBalancerRunning() ) {print("waiting...");sleep(1000);
}

6.3 重新打开balance

如果你关闭了balance,准备重新打开balance

(1) 连接到路由mongos节点

(2) 打开balance

sh.setBalancerState(true)

如果驱动没有命令 sh.startBalancer(),可以用下列命令

use config
db.settings.update( { _id: "balancer" }, { $set : { stopped: false } } , { upsert: true } )

6.4 关于集合的balance

关闭某个集合的balance

sh.disableBalancing("students.grades")

打开某个集合的balance

sh.enableBalancing("students.grades")

确定某个集合的balance是开启或者关闭

db.getSiblingDB("config").collections.findOne({_id : "students.grades"}).noBalance;

6.5 问题解决

mongodb在做自动分片平衡的时候,或引起数据库响应的缓慢,可以通过禁用自动平衡以及设置自动平衡进行的时间来解决这一问题。

(1)禁用分片的自动平衡

// connect to mongos
> use config
> db.settings.update( { _id: "balancer" }, { $set : { stopped: true } } , true );

(2)自定义 自动平衡进行的时间段

// connect to mongos
> use config
> db.settings.update({ _id : "balancer" }, { $set : { activeWindow : { start : "21:00", stop : "9:00" } } }, true )

C/C++Linux服务器开发/高级架构师 系统性学习公开课

Linux服务器开发/架构师面试题、学习资料、教学视频和学习路线图(资料包括C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等),免费分享有需要的可以自行添加学习交流群960994558

MongoDB分片(Sharding)技术相关推荐

  1. MongoDB 分片(sharding)+副本集(replSet)集群搭建

    文章目录 MongoDB安装 Windows平台安装 1.下载 2.安装 3.启动MongoDB服务 4.进入MongoDB后台 Linux平台安装MongoDB 1.下载 2.安装 3.创建数据库目 ...

  2. 【MongoDB】Sharding分片概念及原理

    面对海量的数据,如何提升数据读写效率?了解过DB的应该都知道数据库的分区,分区是主要提升数据查询的效率.面对海量数据的IO能力限制以及扩展性,Sharding是一个利器,我们不用关心具体的实现,从而实 ...

  3. mongodb分片概念和原理-实战分片集群

    一.分片 分片是一种跨多台机器分发数据的方法.MongoDB使用分片来支持具有非常大的数据集和高吞吐量操作的部署. 问题: 具有大型数据集或高吞吐量应用程序的数据库系统可能会挑战单个服务器的容量.例如 ...

  4. MongoDB——MongoDB分片集群(Sharded Cluster)两种搭建方式

    MongoDB分片集群(Sharded Cluster)两种搭建方式 MongoDB分片的概念 分片集群包含的组件 分片集群架构目标 MongoDB分片集群搭建 第一套副本集 第二套副本集 配置节点副 ...

  5. 从原理到实践:Oracle 12.2 Sharding技术揭秘

    何剑敏 Oracle ACS华南区售后团队,首席技术工程师 曾供职于中国联通信息计费部.卓望数码,系统支撑部首席DBA,负责中国移动全网梦网业务和移动应用商城数据库维护.后供职于IBM,负责米其林项目 ...

  6. mongodb分片扩展架构

    目录 一.简介 二.分片集群 三.数据分布策略 四.Mongos访问模式 五.Config元数据 六.分片均衡 参考文档 一.简介 MongoDB目前3大核心优势:『灵活模式』+ 『高可用性』 + 『 ...

  7. 搭建mongodb分片

    搭建mongodb分片 http://gong1208.iteye.com/blog/1622078 Sharding分片概念 这是一种将海量的数据水平扩展的数据库集群系统,数据分表存储在shardi ...

  8. MongoDB 分片的原理、搭建、应用

    一.概念: 分片(sharding)是指将数据库拆分,将其分散在不同的机器上的过程.将数据分散到不同的机器上,不需要功能强大的服务器就可以存储更多的数据和处理更大的负载.基本思想就是将集合切成小块,这 ...

  9. mongodb 分片群集配置 及数据迁移

    配置mongodb分片群集(sharding cluster) Sharding cluster介绍 这是一种可以水平扩展的模式,在数据量很大时特给力,实际大规模应用一般会采用这种架构去构建monod ...

最新文章

  1. web scraper 抓取网页数据的几个常见问题
  2. wtl重载 CListViewCtrl,及其用法。
  3. 【PC工具】常用USB转串口芯片CH340G,更新驱动安装有可能遇到的问题及解决办法...
  4. oracle imp 1403,Oracle中用exp/imp命令参数详解【转】
  5. 更改Android Studio中AVD的默认路径
  6. iPhone 12 Pro系列终于不怕弯了!
  7. 软键盘遮挡住popupWindow问题
  8. 滚动到div的底部?
  9. 22. PHP 日期和时间
  10. e5cc温控仪通讯参数设定_咨询蔚伦触摸屏与欧姆龙温度控制仪E5EZMODBUSRTU的通讯方式...
  11. Java 实训1:编写一个窗体程序显示日历表。
  12. JUCE框架教程(2)—— 创建一个基本的音频/MIDI 插件第一部分:设置
  13. 你理解的精益可能是错的!——从源头重新解读精益
  14. 北京-IT技术狗-顾名思义 解释一下当时随手写下这个名字
  15. oracle按序号排序,Oracle排序以及序号的显示
  16. 代码审计--17--修复方案汇总(上)
  17. 用python画小狗,用turtle画个单身狗送给自己~
  18. ROM、PROM、EPROM、EEPROM、Flash ROM分别指什么?
  19. dede栏目添加自定义字段方法
  20. 第七讲:4.智能物联网开关——角度倾斜报警实验例程

热门文章

  1. 关于如何打开谷歌的电脑设置方法
  2. 线阵相机的优势是什么?如何选择线阵相机?
  3. chart.js-折线图
  4. 什么是高性能计算,涉及哪些技术和知识呢?
  5. 帆软FineReport8.0使用技巧总结及常见问题解决
  6. 更改Excel单元格中批注的显示位置
  7. go语言 使用MTP协议 通过WPD(windows portable device)读取便携式设备信息并进行文件传输
  8. 我六岁时开始使用计算机用英语怎么说,6岁就开始学习编程的她 对计算机技术有着强烈的兴趣 10岁之前,emma 10岁男童的朗诵诗搞 诗朗诵视频...
  9. 解题:肯前必肯后,否后必否前
  10. 2022mathorcup数学建模大数据竞赛B题完整成品来啦!