云计算运维学习---MongoDB中balancer操作

本文基于MongoDB 3.2系列, 最新版本的MongoDB的balancer流程,应该会和3.2有不一致的地方

前言

MongoDB Balancer 是一个运行在 mongos 中的后台线程,该线程的主要作用就是监控 shard 上的 chunk 数量。如果发现某个 shard 上的 chunk 达到一定的数量,则 balancer 会自动的将部分 chunk 块迁移到其它 shard中,保证所有的 shard 中拥有的 chunk 块数量基本一致。

Balancer 的整个运行过程对用户和应用是完全透明的,但是运行过程中,对整个集群的性能有一定的影响。

云计算运维学习---MongoDB中balancer操作

当一个 balancer 进程被激活的时候,负责本次过程的 mongos 节点会通过修改 congfig server 中的一个文档来获取锁,每次都只有一个 mongos 节点负责一次 balance。

Primary Shard

使用 MongoDB Sharding 后,数据会以 chunk 为单位(默认64MB)根据 shardKey 分散到后端1或多个 shard 上。

MongoDB 中每个库会有一个 primary shard,在库创建时分配。

  • 库下启用分片(即调用 shardCollection 命令)的集合,刚开始会生成一个[minKey,maxKey]的 chunk,该 chunk 初始会存储在 primary shard 上,然后随着数据的写入,不断地发生 chunk 分裂及迁移,整个过程如下图所示。
  • 一个库若是没有启用分片地集合,其所有地数据都会存储到 primary shard。

云计算运维学习---MongoDB中balancer操作

何时触发 chunk 分裂?

mongos 上可以通过 sh.disableAutoSplit() 配置项,用于控制是否自动触发 chunk 分裂,默认是开启的。(强烈建议不要关闭autoSplit)

MongoDB 的自动 chunk 分裂只会发生在 mongos 写入数据时,当写入的数据超过一定量时,就会触发 chunk 的分裂。chunk 的默认大小为 64MB,分裂阈值如下:

集合chunk数量 分裂阈值
1 1024B
[1, 3) 0.5MB
[3, 10) 16MB
[10, 20) 32MB
[20, max) 64MB

写入数据时,当 chunk 上写入的数据量超过分裂阈值时,就会触发 chunk 分裂;chunk 分裂后,若是出现各个 shard 上 chunk 分布不均衡时,就会触发 chunk 迁移。

何时触发 chunk 迁移?

默认情况下,MongoDB会开启balancer,在各个shard间迁移chunk来让各个shard间负载均衡。用户也可以手动的调用 sh.moveChunk(fullName,find,to) 命令在shard之间迁移数据。

Balancer 在工作时,会根据 shard tag、集合的 chunk 数量、shard 间 chunk 数量差值来决定是否需要迁移。

(1)根据 shard tag 迁移

MongoBD sharding支持shard tag特性,用户可以给shard打上标签,然后给集合的某个range打上标签,MongoDB会通过balancer的数据迁移来保证「拥有tag的range会分配到具有相同tag的shard上」。

(2)根据 shard 间的 chunk 数量差值迁移

集合 chunk 数量 迁移阈值
[1, 20) 2
[20, 80) 4
[80, max) 8

针对所有启用分片的集合,如果「拥有最多数量chunk的shard」与「拥有最少数量chunk的shard」的差值超过某个阈值,就会触发chunk迁移; 有了这个机制,当用户调用addShard添加新的shard,或者各个shard上数据写入不均衡时,balancer就会自动来均衡数据。
(3)remove Shard触发迁移

还有一种情况会触发迁移,当用户调用 removeShard 命令从集群里移除shard时,Balancer也会自动将这个shard负责的chunk迁移到其他节点。

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大小会随着写入不断增长,直到达到目标大小。

如何减小分裂及迁移影响?

TIP:

(1)当集群中新加入一个 shard 的时候,会导致 chunk 一个不平衡。因为新的 shard 中没有任何的 chunk,所有 mongodb 开始将数据迁移到新 shard 的时候,会花费一定的时间。

(2)当把一个 shard 从一个集群中移除后,会发生类似的过程,balancer 需要花费一定的时间,把这个 shard 中的数据重新分布到其它的 shard,所以在移除 shard 的过程中,一定不要关闭被移除的服务器

1、预分片提前分裂

在使用 sh.shardCollection() 命令对集合进行分片时,如果使用hash分片,可以对集合进行「预分片」,直接创建出指定数量的chunk,并打散分布到后端的各个shard。

通过指定 sh.shardCollection() 命令中 numInitialChunks 参数 指定初始化的分片数量,该值不能超过8192。

如果使用range分片,因为shardKey的取值不确定,预分片意义不大,很容易出现部分chunk为空的情况。

 2、合理配置 balancer

MonogDB的balancer能支持非常灵活的配置策略来适应各种需求。

  • Balancer能动态的开启、关闭
  • Blancer能针对指定的集合来开启、关闭
  • Balancer支持配置时间窗口,只在制定的时间段内进行迁移。如何配置balancer时间窗口,请参考:传送门

 

 

参考文章:

https://blog.csdn.net/joy0921/article/details/80131276

https://bbs.huaweicloud.com/forum/thread-7973-1-1.html

 

 

 

 

 

 

 

 

上一篇:day1作业二:多级菜单操作


下一篇:Java实现堆排序(大根堆),实战