写点什么

TiKV 缩容下线异常处理的三板斧

  • 2022 年 10 月 07 日
    北京
  • 本文字数:5785 字

    阅读完需:约 19 分钟

作者: h5n1 原文来源:https://tidb.net/blog/ddef26a5

1   概述

       TiKV/TiFlash 缩容是 TiDB 运维中经常执行的操作,由于系统本身或缩容过程中操作不当,容易导致 TiKV 处于 offline 状态无法成为 tombestone,造成缩容过程失败。


       本文介绍 TiKV 缩容过程中常见处理方式,适用于 4.X 或以上版本使用 tiup 管理的集群,由于版本差异可能不同版本的执行结果有差异,TiDB 一直在不断完善下线处理过程。


       以下内容为个人经验总结,不当之处还请指正,有其他处理方法也请分享一下。

2   Store 状态转换

      



       在了解 store 状态转换过程前,先了解 2 个基本概念。


       peer:region 是一个虚拟的逻辑概念,每个 region 分配一个 id 是 region_id,一个 region 下默认有 3 个副本,每个副本叫做 peer,各分配一个 peer_id,每个 peer 位于不同的 tikv 实例。


       store: 指的是 TiDB 集群中的 1 个 TiKV 或 TiFlash 实例


       store 的生命周期中包含有多种状态:


  •   Up 


       表示当前的 Store 处于提供服务的正常状态。


  •   Disconnect


       当 PD 和 TiKV 的心跳信息丢失超过 20s 后,该 TiKV 的状态会变为 Disconnect 状态。


  •   Down


       表示该 TiKV 与集群失去连接的时间已经超过了 max-store-down-time 定义的时间,超过该时间后,相应的 TiKV 会变为 Down,并且开始在存活的 TiKV 上补足各个 Region 的副本。


  •   Offline


       当对某个 TiKV 缩容后,该 TiKV 会变为 Offline 状态,该状态只是 TiKV 下线的中间状态,处于该状态的 TiKV 会进行 leader 的    transfter 和 region balance ,当 leader_count/region_count  均显示 transfter 或 balance 完毕后,该 TiKV 会由 Offline 转为 Tombstone。在 Offline 状态时,TiKV 仍能提供服务、进行 GC 等操作,禁止关闭该 TiKV 服务以及其所在的物理服务器或删除数据文件。


  •   Tombstone


       表示该 TiKV 已处于完全下线状态,可以使用 remove-tombstone 接口安全的清理该状态的 TiKV。


       TiKV 节点的状态可通过以下三种方式查询:


       (1)使用 tiup cluster display cluster_name 命令


       (2)使用 pd-ctl –u pd_addr store 命令


       (3)查询 information_schema.tikv_store_status

3   TiKV 下线流程

Tikv 下线为异步过程,其状态过程会经历 UP、Offline、Tombstone 3 个阶段。


(1)   手动转移 leader 和 region


       Tikv 下线过程中最耗时的就是在 offline 阶段的 leader 和 region 转移过程,也是最容易出问题的阶段,为了使下线过程更加可控,建议下线 tikv 节点前先手动转移。


       使用 pd-ctl store weight <store_id> <leader_weight> <region_weight> 设置待下线节点的 leader_weight/ region_weight 为 0。


       对于 leader 转移也可以使用 pd-ctl scheduler add evict-leader-scheduler store_id  添加 evict 调度方式驱逐待下线 store 上的 Leader。


       使用 pd-ctl store 或 information_schema.tikv_store_status 检查待下线节点 leader_count、region_count。


       注意:设置 leader_weight/ region_weight 为 0 并不能保证全部的 laeder/region 都能转移完。若果有少量的遗留可使用第后面章节中的手动添加调度方式进行转移


(2)开始缩容


       缩容命令使用 tiup cluster scale-in cluster_name –N xxx 方式,该命令会调用 PD API 开始下线流程,之后 tikv 状态变为 offline,进行 leader 和 region 转移,当全部转移完成后 tikv 就会转为 tombstone 状态。


       在 store 未转换为 tombstone 状态前禁止使用 –force 选项强制缩容,强制缩容只是不等的 leader/region 转移完成就将 tikv 节点从集群中移除,虽然 tiup cluster display 已无法看到下线的节点但 region 信息依然残留,此时 store 处于 offline 状态、region 无法完成转移。–force 仅适用于 tikv 节点完全宕机或数据目录被删除的极端情况。


       对于 UP 状态的 store pd-ctl store delete 命令也仅仅是将 tikv 设置为 offline 状态,并不是删除 store。在 5.x 版本前可以使用命令强制将 store 转为 tombstone 状态,该命令仅在全部完成 leader/region 转移后才可使用,否则的话会引起异常,因此 5.X 版本后禁止了该命令。


       对于正常操作缩容的节点如果 leader/region 无法正常转移,导致长时间处于 offline 常见的原因有: 其他接的磁盘满了或达到 high-space-ratio 上限导致不能被调度;raft group 工作异常比如无法选主导致无法执行调度。


(3)调整下线速度


       通过 pd-ctl config set 命令可以增大 leader-schedule-limit、replica-schedule-limit、region-schedule-limit 等参数增加 leader/region 的调度速度,加快下线过程,上述命令是用于控制 PD 侧调度命令的产生速度,实际的执行还收 tikv 侧的消费速度限制,通过 pd-ctl store limit <store_id> <limit> 增加消费速度。


(4)清理 tombstone 节点


       当 tikv 节点转变为 tombstone 状态后,使用 tiup cluster display 时会提示使用 tiup cluster prune 命令完成集群清理 Tombstone 节点,该命令会执行以下操作:


  • 停止已经下线 tikv 节点的进程

  • 清理已经下线掉的节点的相关数据文件

  • 更新元数据信息和集群拓扑,移除已经下线掉的节点


(5)再次清理


    有时通过 tiup cluster prune 清理完下线节点后在集群里已经清理完,但监控中仍然会显示 tombone store,可以使用如下命令进行清理:


       pd-ctl -u http://pd_ip:2379 store remove-tombstone
复制代码


       或 


           curl -X DELETE pd-addr:port/pd/api/v1/stores/remove-tombstone
复制代码


(6) 终止下线过程


       处于 offline 状态的节点未成为 tombstone 前可以通过以下命令终止其下线过程,使 tikv 重新成为 UP 状态,不适用已经删除 tikv 数据目录或宕机的情况,部分情况该 tikv 可能需要重启。


       curl -X  POST http://pd_ip:pd_port /pd/api/v1/store/{store_id}/state\?state=Up
复制代码


       上述的下线流程为首先使用 tiup cluster scale-in 方式,缩容操作时也可以使用如下流程:


(1)    使用 pd-ctl store delete 开始下线过程,store 变为 offline。


(2)    待状态变为 tombstone 后使用 store remove-tombstone 清理


(3)    使用 tiup cluster scale-in –force 清理下线节点信息。

4   异常处理三板斧

4.1 第一招:手动调度

       Leader/region 的迁移过程其实就是 PD 下发的一系列 operator,当出现 store 长时间处于 offline 时,可首先尝试使用下面的命令手工添加调度移除待下线 store 上的副本:pd-ctl operator add remove-peer <region_id> <from_store_id>。


       可以参考下面脚本,批量的将 store 上 region 做 remove-peer:


 for i in { <offline_store_id> } do    for j in pd-ctl region store $i | jq ".regions[] | {id: .id}"|grep id|awk '{print $2}'    do     pd-ctl operator add remove-peer $j $i     done    pd-ctl store $i done
复制代码


       手工添加调度方式适合于 tikv 节点上所涉及 region 的 raft 工作正常情况,region 中存在 leader 接收 operator 调度,对于选不出 leader 的情况使用该命令会报 cannot build operator for region with no leader 错误。当出现此类问题时则需要进行多副本失败恢复或重建 region 的操作。


       可使用如下命令找到没有 leader 的 region:


pd-ctl  region --jq='.regions[]|select(has("leader")|not)|{id: .id,peer_stores: [.peers[].store_id]}'
复制代码

4.2 第二招:多副本失败恢复

       region 默认为 3 副本,当有 2 个 tikv 实例出现故障时则会有 region 出现半数以上副本不可用的情况,因此整个 region 变为不可用状态,次数查询该 region 数据会报 Region is unavailable 错误,此时需要进行 region 多副本失败恢复,强制将故障 tikv 上的 region 信息移除,然后由 tikv 自动根据最后剩余的 region 副本进行补齐。


       多副本失败恢复主要步骤如下:


(1)    停止 region 调度,将 limit 相关参数调整为 0


使用 pd-ctl config show|grep limit > limit.config 记录当前配置


使用 pd-ctl config set region-schedule-limit 0 设置 limit 相关参数为 0


(2)    停止待下线节点上 region 涉及的所有的 tikv 实例,一般情况涉及 region 数量较多需要停止所有 tikv 实例。


可使用如下命令查找故障节点上多数副本失败的 region(if 里指定 store_id 列表):


pd-ctl   region --jq='.regions[] | {id: .id, peer_stores: [.peers[].store_id] | select(length as $total | map(if .==( 4,5,7) then . else empty end) | length>=$total-length)}'
复制代码


(3)    在正常的 tikv 节点上执行恢复命令


tikv-ctl --db /data/v5.0.3/tikv/data/db unsafe-recover remove-fail-stores -s 3 -r 1001,1002
复制代码


       当问题 tikv 上仅有少量 region 时可以使用上述命令,并且仅需关闭 region 涉及的 tikv 并执行。其中 -s 为待下线的问题 store_id,-r 为该 store 上的 region。如果想要移除 store 上的 region 可使用 –all-regions 选项


tikv-ctl --db /data/v5.0.3/tikv/data/db unsafe-recover remove-fail-stores -s 4,5,7 --all-regions
复制代码


使用时需注意以下几点:


  • 涉及的 region 所在的正常 tikv 必须关闭方可进行,如果使用 –all-regions 则必须关闭所有正常的 tikv 实例,然后在所有的正常节点上执行

  • 不同版本命令有差异 –data-dir 时需要为部署时的 data-dir 目录,使用 –db 时为 data-dir 下的 db 目录


(4)    重启 tidb 集群


       做完多副本失败后使用 pd-ctl store 检查刚才处理的 store 会,不同的 TIDB 版本会出现如下不同的情况


  • 故障节点的 tikv 会从集群正常移除,系统正常运行。

  • 如果为 tombstone 状态,此时可以按照前面的操作 remove-tombstone。

  • 如果为 down 状态则可以 store delete 使其成为 tombstone 后清理。

  • 如果状态仍为 offline 且 leader/region count 不为 0 可再次进行 unsafe-recover 直到为 0。如果有全副本丢失的话则可能 leader/region count 为 0 后仍然为 offline 状态,需要重建 region,所涉及的 region 重建后就会变为 tombstone,具体操作见下一节。


       如果由于多个 store 故障导致某些 region 的副本全部丢失可能会无法正常启动 tikv 此时需要 recreate-region 方式创建空 region,如果很不幸这些 region 是系统表使用由于数据丢失还会有其他问题。


(5)    恢复 limit 调度参数


恢复调度后会为缺失副本的 region 补充副本,可使用如下命令检查副本数为 1 的 region(length 指定副本数):


pd-ctl region --jq='.regions[] | {id: .id, peer_stores: [.peers[].store_id] | select(length==1) } '
复制代码


       多副本失败恢复也适用于仅 1 个 tikv 实例故障时的处理,缺点是需要停止所有 tikv 实例影响系统可用性,因此 6.x 版 TiDB 支持在线的多副本失败自动处理,详细过程可参考官方文档:https://docs.pingcap.com/zh/tidb/stable/online-unsafe-recovery


       更多关于多副本失败恢复的过程文章可在 asktug 搜索。

4.3 第三招:重建 region

       如果 region 的副本全部丢失或仅少量的几个无数据空 region 无法选出 leader 时可以使用 recreate-region 方式重建 region。


(1)    副本全部丢失,执行了多副本失败恢复


检查副本全部丢失的 region,if 内指定故障 tikv 的 store_id


pd-ctl region --jq='.regions[] | {id: .id, peer_stores: [.peers[].store_id] | select(length as $total |map(if .==(4,5,7) then . else empty end)|length>$total-length)}' |sort
复制代码


(2)    少量 region 无数据且无法选主,未对集群做任何处理


       使用 curl http://tidb_ip:10080/regions/{region_id} 检查该 region 上的对象信息,如果 frames 字段为空的话则说明该 region 为无数据的空 region,重建无影响,否则会丢失数据。


(3)    重建 region


       关闭 region 涉及的存活 tikv 实例,然后在其中一个正常 tikv 上执行:


    tikv-ctl --data-dir /data/tidb-data/tikv-20160 recreate-region -p 'pd_ip:pd_port' -r  <region_id>
复制代码


       注意:以前版本使用 –db 参数而非 –data-dir,指定目录为正常 tikv 的。另外复制命令时注意引号、单横线是否是中文格式。


(4)    重启 tikv


       如果之前 unsafe-recover 后 store 状态仍为 offline,重启后正常 tikv 会成为 tombstone 状态 (有时需要 pd-ctl 直接指定下线 store_id 查看),然后 remove-tombstone 即可。


  除了使用recreate-region重建外,也可以尝试tombstone region方式:
复制代码


tikv-ctl --db /path/to/tikv/db tombstone -p 127.0.0.1:2379 -r <region_id>,<region_id> --force
复制代码

5   总结

       TiDB 支持在线扩缩容,在缩容时如果理解 store 状态转变和每步处理过程并按流程操作出现异常情况的概率相对较小,随着版本的变化也在一直不断改善缩容过程的处理,降低系统自身问题的概率,针对缩容时的操作建议如下:


(1)    系统部署时对于单机多 tikv 的情况一定要打上 label 标签,保障同一服务器上不同的 tikv 实例在 isolation-level 具有相同的 label,避免将相同 region 的多个副本调度到同一服务器,从而因服务器故障造成多副本丢失。


(2)    缩容 tikv 时应尽量提前进行 leader/region 转移,使缩容过程更加可控。


(3)    缩容时、store 处于 offline 状态时禁止使用 –force 参数,仅对宕机无法修复、数据目录被删除的场景使用。


(4)    缩容多个 tikv 时要尽量一个一个的进行处理,避免一次下线多个时出现问题,尤其是同一服务器上的多个 tikv。


(5)    缩容时要保障其他的 tikv 节点有足够的磁盘空间接收转移的 region。


(6)    如果允许尽量使用高版本数据量。


(7)    做完多副本失败恢复后要检查数据是否一致。


(8)    注意使用 tikv-ctl 等工具时要不同的版本会有不一样的参数,如 –db 或 –data-dir。


发布于: 刚刚阅读数: 3
用户头像

TiDB 社区官网:https://tidb.net/ 2021.12.15 加入

TiDB 社区干货传送门是由 TiDB 社区中布道师组委会自发组织的 TiDB 社区优质内容对外宣布的栏目,旨在加深 TiDBer 之间的交流和学习。一起构建有爱、互助、共创共建的 TiDB 社区 https://tidb.net/

评论

发布
暂无评论
TiKV缩容下线异常处理的三板斧_实践案例_TiDB 社区干货传送门_InfoQ写作社区