血泪教训 TiKV 多副本丢失 unsafe-recover 恢复记录
作者: realcp1018 原文来源:https://tidb.net/blog/9163546d
【是否原创】是
【首发渠道】TiDB 社区
一、问题背景
某集群替换 5 台机器中的 3 台后,由于 store 空间使用率已超过阈值,旧节点上的 region 和 leader 有一部分 (约 2000*9 个左右) 未能完全迁移到其他节点 (通过 grafana 可观察到),导致旧节点的 tikv 一直处于 pending offline 状态。为尽快清理旧机器,某天早上失智直接 force scale-in 强制缩容了所有 3 台旧机器上的 tikv 实例。
强制缩容一段时间后,业务报某些查询出现“Region is unavailable ”9005 编号的报错。查看 tidb 日志找到一个具体的问题 region,发现其 leader 处于被强制缩容的 store 上,并且 3 副本中 2 副本已丢失,导致 leader 无法选举。
推测集群中目前存在一些 2 副本丢失或 3 副本全部丢失的 region,需要执行多副本丢失恢复流程。
二、恢复准备
查看官方提供的《多副本丢失处理方案.pdf》文档,需要先找出 3 副本丢失的全部 region ID(因为重建 region 时会用到)。直接使用文档中提供的下述 pdctl –jq 语句发现查询多副本丢失的 region 会返回为空,因此需要使用其他方式统计出 3 副本丢失的 region ID 列表。
pd-ctl -u http://{pd_ip}:2379 region --jq=".regions[] | {id: .id, peer_stores:[.peers[].store_id] | select(length < 2)}"
2.1. 通过 pdctl 获取到所有旧机器上的 store ID 列表。
pdctl -u {pd_ip}:2379 store --jq=".stores[]|{id: .store.id, address: .store.address, status: .store.state_name, region: .status.region_count, leader: .status.leader_count}" | grep Offline // 找出位于旧机器上的所有store_id,jq功能需要yum -y install jq开启
2.2. 通过查询 /pd/api/v1/regions 接口,过滤出所有 3 peer 全部位于上述 store ID 列表中的 region,此类 region3 副本已丢失。
下述为查询的简易脚本,替换其中的解释性代码为实际值:
findEmptyRehion.py (999 字节)
2.3. 将 2 中的 region 列表存于 emptyRegions.txt 文件中 (见上述代码)
三、恢复流程
按文档流程执行如下:
3.1. 关闭 pd 调度
// 记录当前调度参数,pd-ctl 中执⾏ config show // 关闭调度 scheduler pause balance-leader-scheduler scheduler pause balance-region-scheduler scheduler pause balance-hot-region-scheduler config set replica-schedule-limit 0 // 查看调度是否完成 operator show
使用下述命令关闭 pd 调度更为稳妥 (记下原值方便之后恢复):
config set leader-schedule-limit 0 //4 config set region-schedule-limit 0 //4 config set replica-schedule-limit 0 //8 config set merge-schedule-limit 0 //8 config set hot-region-schedule-limit 0 //4
3.2. 拷贝与集群版本相同的 tikv-ctl 到所有正常 tikv 节点
scp .tiup/components/ctl/v4.0.8/tikv-ctl <新机器>:/home/tidb/
3.3. 停止所有 tikv 节点
tiup cluster stop {cluster-name} -R tikv
3.4. 在所有正常的 tikv 节点执行下述 remove-fail-stores 指令
./tikv-ctl --db /path/to/tikv-data/db unsafe-recover remove-fail-stores -s <2.1步骤中得到的store-id列表,逗号分割> --all-regions // 单机多store时针对每个store执行一次 // 实测速度较快,单store 1TB左右的目录可以在2s内返回
3.5 恢复空洞 region(3 副本丢失的 region)
任意找一个正常的 store:
for region_id in
cat emptyRegions.txtdo ./tikv-ctl --db /path/to/tikv-data/db recreate-region -p {pd_ip}:2379 -r $region_id done // 谨慎起见先echo下生成的命令语句 // 实测恢复速度约为1.5s一个新region,可据此估算全部耗时
3.6 启动 tikv 并恢复 scheduler
tiup cluster start {cluster-name} -R tikv
scheduler resume balance-leader-scheduler scheduler resume balance-region-scheduler scheduler resume balance-hot-region-scheduler config set replica-schedule-limit 2048 // 通过修改limit禁用pd调度的改回原值即可
四、后期检查
// 若存在数据索引不⼀致情况,重建索引,下述admin指令返回错误时即需要重建 // 重建时先创建替代索引,之后重建旧索引,最后删除替代索引 // RawKV 集群不需要执⾏该步骤 ADMIN CHECK TABLE tbl_name [, tbl_name] ...;
五、事故回放
默认 tidb 为 3 副本架构,实际部署中基本不会修改,因此当一次性替换或下架超过 2 台机器时,需要考虑多数副本丢失的问题。
一般来说替换过后需要等待新实例状态变为 tombstone 才可以缩容,但本例中由于磁盘使用率高导致旧机器中剩余一些 region 未能迁移到新节点,实例状态保持为 pending offline。此时应当考虑放大磁盘空间阈值或扩容来确保剩余的 region 被调度走。
本次事故中出现多副本丢失的 region 个数有 7005 个,其中 5715 个为 2 副本丢失,1290 个为 3 副本丢失,这 1290 个 region 的数据已经永久丢失只能通过其他方式补回。
本次事务中多副本丢失的 region 可以通过查询 information_schema.TIKV_REGION_STATUS 来获取其所属的表,幸运的是这个系统表所属的 region 未出问题,据此查到本次多副本丢失的 region 涉及 3 个业务表,可以缩小故障范围方便之后的校验和数据补全,还可以查看 region 存放数据还是索引以便评估损失的数据记录数。
最后,感谢 @这道题我不会 以及他的 5 个小伙伴的鼎力支持。😭
版权声明: 本文为 InfoQ 作者【TiDB 社区干货传送门】的原创文章。
原文链接:【http://xie.infoq.cn/article/8b737b9cba612c28798dcb361】。文章转载请联系作者。
评论