0
2
5
0
专栏/.../

血泪教训 TiKV多副本丢失unsafe-recover恢复记录

 realcp1018  发表于  2021-12-03

【是否原创】是
【首发渠道】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 incat 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个小伙伴的鼎力支持。😭

0
2
5
0

版权声明:本文为 TiDB 社区用户原创文章,遵循 CC BY-NC-SA 4.0 版权协议,转载请附上原文出处链接和本声明。

评论
暂无评论