18.MongoDB之balancer

可以参考分片集群的介绍  这里

可以参见chunk预分片的介绍  这里

关于均衡及官网介绍 这里 这里

前言:使用MongoDB当你对Chunk、Split、Balancer(甚至于jumbo chunk、autosplit)有一定了解后,Mongo对于你就不在是一个整体了,分分合合、动态平衡的视角应该在你的脑海中呈现。

一、balancer(均衡器)简介

1、简介

①Balancer是一个监视各个shard上的chunk数的后台进程;

②他运行在Config Server副本集的primary节点上。

③当给定分片上的chunk数达到特定的 migration thresholds(迁移阈值) 时,均衡器会尝试在分片之间自动进行chunk迁移,以使得每个分片上的chunk数“相同”(注:也并非完全的一个不差)。

④分片集群的平balance过程对用户和应用程序层都是完全透明的,只不过在执行该过程时可能会对数据库性能产生一些影响。默认情况下balanced进程是一直开启的。

扫描二维码关注公众号,回复: 14463716 查看本文章

2、chunk迁移会对数据库性能有负面影响

        chunk迁移会在带宽和工作负载方面会带来一定的开销,这两方面都会影响数据库性能。均衡器通过以下方式将影响降至最低:1)限制分片在任何给定时间最多只有一个迁移;也就是说一个shard不能同时参与多个块迁移。举个例子:为了从一个shard迁移多个块,均衡器会一次迁移一个块进行多次迁移,而不是多个块同时迁移。2)仅当分片集合中块数最多的分片与该集合中块数最少的分片之间的块数差异达到迁移阈值时,才触发平衡操作。

注:从MongoDB 3.4开始,MongoDB可以执行并行chunk迁移。观察到一个shard一次最多只能参与一次迁移的限制,对于一个有n个shard的shard集群,MongoDB最多可以同时进行n/2(向下舍入)块迁移。

另外用户可以暂时停用平衡器进行维护。有关详细信息,请参阅禁用平衡器。

默认情况下balancer始终处于开启状态。

二、balancer(均衡器)相关指令

1、balancer基本指令

(1)查看balance状态(是否开启)

sh.getBalancerState()

注:也可以在mongos上执行sh.status()查看balance状态。

(2)查看balancer是否在工作(是否正在有数据迁移)

sh.isBalancerRunning()

 (3)开启balancer功能

sh.setBalancerState(true)

(4)关闭balancer( 停止balancer)

sh.stopBalancer()

注:关闭balancer要注意确保没有任务处于执行状态,如果正在执行块迁移指定关闭命令可能引发数据不一致。如下提供了一个工具:在运行就是输出“waiting...”,此时等待一下;如果直接退出则说明没有chunk在迁移,此时可以关闭balancer。

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

2、balancer支持窗口时间

        均衡器在执行块迁移操作时候会占用实例中节点的资源,对业务多少会有些影响。为了避免块迁移给业务带来影响我们可以设置均衡器的活动窗口,让其在指定的时间段内工作。步骤如下:

(1)mongos命令行切换至config数据库

use config

(2)执行如下命令设置balancer的活动窗口

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


db.settings.update(
   { _id: "balancer" },
   { $set: { activeWindow : { start : "00:00", stop : "06:00" } } },
   { upsert: true }
)
<start-time>:开始时间,时间格式为HH:MM(实例所在地域的当地时间),HH取值范围为00 - 23,MM取值范围为00 - 59。
<stop-time>:结束时间,时间格式为HH:MM(实例所在地域的当地时间),HH取值范围为00 - 23,MM取值范围为00 - 59。

 MongDB会以config数据库的primary节点的时间为参考,开始执行chunk的迁移。

(3)可通过sh.status()查看balancer的活动窗口

(4)移除balancer搬迁时间窗口

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

(5)备份和balancer。

         MongoDB中,不要在备份的时候启用balancer,否则,备份的数据将会不一致。通常情况下,备份的时间窗口要和balancer的时间窗口错开,如果balancer没有设置时间窗口,则在备份的时候,关闭balancer。

        要确保时间窗口足够搬迁完所有的数据,否则数据库将一直处于不平衡的状态。

三、balancer效果验证

1、关闭balancer查看效果

        当前某集群存在jumbo chunk的问题,另外业务量也相对较大,综合表现为cpu占用过高。

        现在尝试关闭balancer看看cpu是否能降低。另外再尝试关闭 auto split观察效果如何。

2021年11月26日14:56执行关闭指令,对比30分钟后监控。

结论:好像有一点点作用,但十分有限;大概就是98%变成96%这个样子。也就是说cpu高并不是因为balancer,从这个角度可以知道balancer为降低对业务的影响确实“很克制”。针对cpu高的问题,可能就是autosplit导致的了。

2、关闭autosplit查看效果——就是它

2021年11月26日15:40关闭了autosplit。首先分片0的cpu占用就立马下来了;十分钟后分片1的占用也下来了;再过20分钟后分片2的也降下来了。关于这一点是因为虽然关闭autosplit能立即生效但是对于正在执行的过程需要等执行结束,是完全可以说通的。可以参考  Mongodb预分片(pre-split)和autosplit(chunk相关)_mijichui2153的博客-CSDN博客

注:测试下来关闭autosplit到具体生效可能确实需要一定时间,0~30分钟量级。

显然效果很显著,如下。

分析与结论:

        究竟是正常的的写入操作引发的split是的cpu过高,还是因为jumbo chunk 的原因导致mongodb不断尝试split但是又一直split不了导致的cpu过高呢??为此观察chunk数量。

①首先把autosplit打开,马上cpu又飙升上来了;

 ②然后2021年11月28日10:50统计chunk数为6658,如下:

③过了三十分钟发现依然是6658,由此可见并没有chunk被真正的split,如下:

结论:从测试结果来看腾讯云MongoDB针对jumbo chunk跳过split的机制不够彻底,mongos发出split请求后依然还会尝试做不少事情(每次有这个块的数据写入就会触发),以至于占用过高cpu影响数据库性能。也就是说我们要尽量避免jumbo chunk,否则数据库会被无效split拖垮。对于这种情况关闭autosplit貌似还可以接受;但是切记关闭autosplit要非常慎重。

-------------------------------------------------更新2022年02月23日----------------------------------------------------

关于上面说的无谓split导致cpu占用过高的问题。在mongodb的后续版本中应该是予以解决了的。

[SERVER-42273] Introduce a "force" option to `moveChunk` to allow migrating jumbo chunks - MongoDB Jira

大致意思就是4.4版本:"4.4版本支持{force}选项来迁移jumbo chunk。均衡器也新增了attemptToBalanceJumboChunks配置。如果一个块已经被标记为jumbo了,也就不会再尝试split或者搬迁它了" 。

四、一些现象及解释

1、cpu占用一分钟一个尖刺 如下图。

原因很简单就是checkpoint导致的。 

猜你喜欢

转载自blog.csdn.net/mijichui2153/article/details/121558840