Merge-region 原理及常见问题
作者: Aunt-Shirly 原文来源:https://tidb.net/blog/2e4a8fb2
Why: 为什么要 merge region
Merge-region 顾名思义就是合并 region, 主要是指将数据范围相邻小 region 合并起来,以减少 region 的总个数。之所以要 merge-region, 主要是以下两个原因:
Region 信息维护需要消耗资源:当小 region 数量太多时,维护 region 的元数据信息、raft-group 心跳等都需要额外的资源开销,而这些开销累计到一定程度就会对我们集群产生性能影响。
Region 是大部分 TIKV 读写请求的基本单位,因此 region 太小太散会直接导致 到 TiKV 的读写请求变得零散,导致请求无法批量化处理。如一个 100 M 的 region 被切分成了 100 个 1 M 的 region, 那么读取这一个 region 的数据就需要发送 100 个请求给 KV。
When: 什么情况下需要 merge-region
删除了大量数据
批量连续空间删除:truncate/drop table/partition 删除了大量数据并过 GC lifetime 后,会产生大量的 empty region
零散空间删除:delete/update/insert 下每行数据 mvcc 版本较多时,在过了 gc lifetime 并完成 compact 后,会产生 undersized-region/empty-region, 也是需要 merge 的
用户觉得集群 region 数量太多而突然调大了 region size ,此时会在短时间内产生很多 undersized-region 并开始 merge:
调大 region-size 方式
如何查看 merge-region 的进度
在 pd->region-health 面板上看到以下两个指标时,需要特别关注:
empty-region-count
: region size <= 1 Mundersized-region-count
: region size <=schedule.max-merge-region-size
且 region keys <=schedule.max-merge-region-keys
, 也就是符合 merge 条件的 region .
How: 如何加速 region merge
PD 作为集群的大脑,掌控着整个集群的健康度,其中一项重要的任务便是 region 的健康度。当发现 region 出现异常时,如我们发现了很多 empty 或者 undersized 的 region, 这些 region 在比较多时,会对 region 元数据维护这一块产生很大的压力,从而影响集群整体性能。 因此 PD 在检测到这类异常后,就会发起相应的调度操作,指导 TiKV 中的 region 去完成自我修复功能。对于小 region 来说,PD 会给出 merge region 的指令,指导 TiKV 中对应的 region 去完成 region merge 的过程。
因此,加速 region merge ,主要是要加速以下两个事情:
PD 侧 region-merge operator 生成的速度
TiKV 侧 region-merge operator 消费的速度
加速 PD 侧 merge-region operator 的生成速度
Merge region 是在 PD 做 region 健康度检查 时的最后一步进行, 如果 region 在前面的检测过程中没有遇到任何异常,最后就会走到 merge 这一步检查。主要涉及的参数有:
split-merge-interval 对于刚 split 出来的 region, 或者集群刚启动时,需要等待这个时间完成才会开始 merge
Merge-scheduler-limit: 8 by default. Check pd->operator->Schedulers reach limit
特别注意:Store-limit 不会对 merge 产生影响。
Merge-region operator 生成条件 (MergeChecker.Check):
PD 在对 region 进行合并检查时,会检查一系列参数,当 merge-region operator 创建失败时,也会在 pd->scheduler->region merge checker 里面记录详情:
有了该监控后,我们就可以很快找到 merge-region operator 没有生成的原因,再展开下一步诊断。下面我们按照 merge region 在这一过程中的检查顺序对图中的指标展开详细介绍:
paused
: merge_checker 已经禁用recently-start
: 最近启动的 split-merge-interval(default 1h) 内,默认该 region 刚分裂过,不会被合并recently-split
: 最近 split-merge-interval(default 1h) 内刚分裂出来,不会被合并skip-uninit-region
: region 没有 leader, 一般发生在 pd 刚启动,需要从底层存储或者 tikv 上报该 region 的心跳才能知道 leaderno-need
: region 比较大,不需要合并。检查依据:max-merge-region-size
和max-merge-region-keys
都要符合条件才行special-peer
: region 有 down 或者 pending 副本abnormal-replica
: region 有异常,比如缺副本或者副本没有按照 placement-rule 放置hot-region
: 热点 region 不 mergeno-target
: 找不到可以跟它合并的 regionadj-not-exist
: 找不到相邻的 regionadj-recently-split
: 相邻 region 最近刚 split 过adj-region-hot
: 相邻 region 有热点adj-disallow-merge
: 相邻 region 不允许合并,原因可能如下:两个 region placement rule 不一样
其中一个 region 被打上了
merge_option=deny
的 labelenable-cross-table-merge
为 false, 且两个 region 属于不同表adj-abnormal-peerstore
: 要合并的两个 region 在异常 store(正在 offline 或者 不见 了) 上都有副本adj-special-peer
:相邻节点有 down 或 pending 的副本adj-abnormal-replica
: 相邻 region 有异常,比如缺副本或者副本没有按照 placement-rule 放置target-too-large
: 合并后 region size 会变成超大 region, 比如大于 region-max-size *4split-size-after-merge
: 合并后 size 大于 region-max-size,又能达到 split 的标准。也就是即使合并了也会很快被 split 开,就会拒绝合并。split-keys-after-merge
: 同上,只是单位变成 keys. 也就是合并后很快会达到 split 条件而再次被切开。拒绝合并larger-source
: source region 的 size 或者 key 个数要比合并的 region 多,只是标记一下,这个 operator 还是会生成。
加速 merge-region 的消费速度
说到 merge-region 的消费速度,首先我们需要知道 region-merge 是怎么做的。
Region 本身是一个逻辑概念,作为 TiKV 数据存储的最小逻辑单位,它背后的数据副本是实打实的物理存储在 tikv 上。因此在做 region merge 的时候,我们首先会将要合并的 两个 region 副本数据及角色的拓扑结构调节到完全一致,最后再安全快速的进行逻辑上的合并。
下面我们以 region 2[B,C) 与 region3[C,D) 合并成 region2[B,D) 为例子,简要讲一下 region merge 的过程:
初始化状态下:
Region 2 的数据范围为 [B,C), 三个副本分别在 store-1, store2,store-3 上,其中 leader 在 store-2 上
Region 3 的数据范围为 [C,D), 三个副本分别在 store-1, store-2, store-4 上,其中 leader 在 store-4 上。
要合并 region 2 和 region 3 , 首先我们需要将两个 region 对应的副本搬迁到相同的 store 上,假设在这个阶段,我们会将 region-2 在 store-3 上的副本搬迁到 store-4 上。
现在,两个 region 分别在 store-1, store-2, store-4 上各有一个副本了,但是要进行合并,我们还需要这两个 region 的副本角色分布拓扑完全一致,因此,这里我们将 region-2 的 leader 迁移到 region-3 leader 所在的节点 store-4 上:
现在,region-2 和 region-3 的副本角色拓扑完全一致了,我们就可以安全地完成逻辑合并:
从 merge-region 的执行原理我们了解到,对于 merge-region 来说,merge 过程中需要将对应的 region 搬迁到相同的 store 上,因此 TiKV 副本搬迁相关的配置都会影响 merge-region 执行的速度。最消耗资源也是最容易成为瓶颈的也是这一块 add-learner,具体调优手段可以看本 KB 第二章 [Troubleshooting Guide]Deep dive into TiKV node scaling and common issues, 这边我们不详细展开。 关键配置:
通过 PD 日志查看特定 region 的 merge 进度
日志 example:
在 merge 特定 region 卡住时可参考该日志
最近对 merge 优化的几个 issue
针对 empty region 等小 region 的副本搬迁性能得到显著提升 tikv#17408
针对小 region 的数据搬迁,对于小于
snap_min_ingest_size
(默认 2MB)的 region 搬迁,将由原来的 ingest 方式改成直接往 rocksdb 写入的方式。针对 empty region(<1M) 比较多的场景,会有显著的性能提升针对数据搬迁过程中 region-worker 因 delete-range 和 generate-snapshot 任务堆积导致搬迁卡住的问题在 tikv#12587 也得到了有效缓解。
常见问题及处理
Empty region 无法合并:Placement-rule 不同导致相邻 region 无法合并(符合预期)
现象:用户在开启了 enable-cross-table-merge 的情况下,设置了多个 placement rule, 比如 table-1、 table-2、table-3 分别设置了不同的 placement-rule, 其中:
table 1 要求放在北京、上海
table 2 要求放在杭州、山东
Table 3 要求放在北京、上海
其中,table 1\table 2\table3 的 table-id 连续,也就是数据区域连续,也就是所在的 region 数据范围连续
此时,如果 table2 被 drop 掉后产生了空 1 个空 region, 这个空 region 是无法与 table1 或者 table3 的 region 合并的,这个时候就产生了空 region 一直无法被合并的情况。related KB
workaround: 将 table2 的 placement-rule 设置成与 table 1 或者 3 一样。
主从集群空 region 合并速度差异大
现象:当主从集群的 merge region 相关参数不一致时,可能导致两套集群合并速度相差很大。比如有用户将 merge region 的两个判断条件设得不一致:
max-merge-region-size (主 20M,备 1 M),也就是说主集群只要 region 20 M 以内的就可以 merge, 但是备集群必须在 1M 内的 region 才可以 merge
max-merge-region-keys (主 200K,备 1 K), 同理,主集群比备集群多了 1K-200K 个 key 的 region 可以 merge
workaround:将备集群的参数与主集群调整到一致
Merge region 相关的内存泄漏
现象:大量的 merge region 操作可能导致统计信息上出现内存泄漏,导致 PD 内存持续上涨
被合并的 region 滞后的心跳可能导致当前 region 的信息永远残留在 PD 内存中 pd#8710 pd#8700
被合并的 region 因为不会再发送心跳导致留在 hot-region 的缓存无法清理 pd#8698
workaround:
定期重启 PD
升级到已经修复的版本
版权声明: 本文为 InfoQ 作者【TiDB 社区干货传送门】的原创文章。
原文链接:【http://xie.infoq.cn/article/e9ee6fa82375a75fcb3df400a】。文章转载请联系作者。
评论