写点什么

TiDB 多数派节点故障恢复指南

  • 2024-05-31
    北京
  • 本文字数:4527 字

    阅读完需:约 15 分钟

作者: 这里介绍不了我原文来源:https://tidb.net/blog/b72c3144

1. 背景


(1) 我们所使用的 TiDB 目前采用 3 副本的部署方式,其中一份数据同时存储在多个节点中。然而,如果一个 Region 的多数或全部副本在短时间内全部下线,该 Region 将无法进行读写操作,对业务造成严重影响。


(2)在实际生产过程中,我们也曾遇到同一台交换机发生灾难性故障,如机房断电等情况,其下的多个 TIKV 宕机,也会造成多副本或全部副本丢失,导致业务不可用的情况。



(3)社区当前多数文章只针对某一个版本在该场景下进行了故障恢复。而在 V6.1.0 正式引入 Online Unsafe Recovery 功能,所以本文将整合 V6.1.0 版本及其之前和之后的两个版本在该场景下故障解决方案。

2. 原理介绍

对于 PD 来说,是如何获取某个 Region 的状态?


对于每个 Raft Group 的 Leader 和 PD 之间都存在心跳包,用于汇报这个 Region 的状态。心跳包中主要包括:


  • Leader 的位置

  • Followers 的位置

  • 掉线副本的个数

  • 数据写入 / 读取的速度


除此之外,PD 还会收集每个 TiKV 节点(Store)发送的心跳包。通过这两种心跳包得到的信息,PD 会通过一些策略来制定具体的调度计划。


而调度的基本操作大致分为:


  • 增加一个副本(addReplica)

  • 删除一个副本(RemoveReplica)

  • 将 Leader 角色在一个 Raft Group 的不同副本之间进行迁移(TransferLeader)


假设我们现在有若干个 Region 分布在 5 个 Store 上,并且每个 Region 有 3 个副本,我们进行实验,手动挂掉 3 个 Store 。若剩余副本数等于 2,PD 可以通过调度进行 Leader 的重新选举以及副本的补充。但是若只剩余 1 个副本,那么就需要人工介入进行恢复。

3. 实验模拟

首先,使用 tiup-bench 工具来准备一些测试数据:


tiup bench tpcc prepare --warehouses 4 --db xxx -H xxxx -P 4000 -pxxx
复制代码

3.1 V6.1.0 以下版本(3 副本丢失 2 副本)

集群 store 情况:



这里用 IP+store id 代替真实 IP 地址。


Region 分布情况:



实验过程:


(1)集群正常状态



所有表均可访问


(2)在 store 1 和 11 上 mv data 文件夹


移动后,store 1 和 11 两个 TiKV 节点状态变为 Disconnected。



(3)停止 store 1 和 11 的服务


这里要将 store 1 和 11 TiKV 服务不可用才能无法访问上述表。否则就会出现还能访问的情况。



TiKV 服务的配置文件一般在 /etc/systemd/system/tikv- 端口号.service 中。


需要将 Restart 置为 no,因为 Restart=always: 只要不是通过 systemctl stop 来停止服务,任何情况下都必须要重启服务。


再将 TiKV 进程 KIll 掉。


(4)访问对应表




符合我们的预期,3 副本状态下挂掉 2 个副本,访问 item 表不受影响,访问其他表会报错 : Region is unavailable


(5)待修复 Region


核心原理在于使用单副本数据进行多副本补充,如下表所示:



所以我们需要在正常的 Store 上对副本进行补充:


在 Store 2 上修复 Region 34867、34879、34788 和 34776。


在 Store 3 上修复 Region 34780、34847、34743、34826 和 34830。


在 Store 10 上修复 Region 34764、34855、34839、34871 和 34875。


(6)开始修复


停止 TiKV 角色


tiup cluster stop 集群名称 -R tikv
复制代码


关闭 PD 调度


config set region-schedule-limit 0
config set replica-schedule-limit 0
config set leader-schedule-limit 0
config set merge-schedule-limit 0
复制代码


修复 Region


这里使用 tikv-ctl 工具,需要到对应的 TiKV 节点去执行命令进行修复,如果是使用 TiUP 部署的集群,tikv-ctl 工具在 ~/.tiup/components/ctl/{VERSION}/ 目录下,拷贝到对应的 TiKV 节点(Store)上。


-s 是宕机的 TiKV 节点的 store id,-r 是我们要移除的 Region id(多个请以逗号分隔)。


Store 2:


tikv-ctl --data-dir /data/tidb/data unsafe-recover remove-fail-stores -s 1,11 -r 34867,34879,34788,34776
复制代码


Store 3:


tikv-ctl --data-dir /data/tidb/data unsafe-recover remove-fail-stores -s 1,11 -r 34780,34847,34743,34826,34830
复制代码


Store 10:


tikv-ctl --data-dir /data/tidb/data unsafe-recover remove-fail-stores -s 1,11 -r 34764,34855,34839,34871,34875
复制代码


执行成功会显示



(7)启动集群,校验数据


tiup cluster start 集群名 -R tikv
复制代码



这里注意,store 1 和 11 是无法启动的,因为数据目录已经被 mv 了。



经过修复,上述表可以正常访问。


(8) 节点下线


最后可以将 store 4、7 对应的 TiKV 节点强制下线


tiup cluster scale-in cluster-name -N IP1:20260,IP11:20260 --force
tiup cluster prune cluster-name
复制代码

3.2 V6.1.0 以上版本(3 副本丢失 2 副本)

在 V6.1.0 版本后,推出了在线有损恢复 Online Unsafe Recovery,现在,我们将使用这种方法进行故障恢复。


集群 store 情况:


| id | address || – | ——- || 1 | IP1 || 2 | IP2 || 3 | IP3 || 10 | IP10 || 11 | IP11 |


同上,这里用 IP+store id 代替真实 IP 地址。


Region 分布情况:



基于上述 Region 分布情况,假设我们关闭了 store 2 和 store 3 ,那么以下表将无法访问:district、item、new_order、order_line 和 stock。而不受影响的表包括:customer、history、orders 和 warehouse。


实验过程:


(1)集群正常状态



所有表均可访问


(2)在 store 2 和 3 上 mv data 文件夹



(3)访问表(在线有损恢复,不需要停止 store 2 和 3 的服务,这里要注意)



(4)执行恢复命令


unsafe remove-failed-stores 2,3
复制代码


执行成功如下:



(5)查看恢复进度


unsafe remove-failed-stores show
复制代码


[  {    "info": "Unsafe recovery enters collect report stage",    "time": "2024-04-08 16:58:23.847",    "details": [      "Failed stores 2, 3"    ]  },  {    "info": "Unsafe recovery enters force leader stage",    "time": "2024-04-08 16:58:24.157",    "actions": {      "store 1": [        "force leader on regions: 70, 351, 411"      ],      "store 10": [        "force leader on regions: 30"      ],      "store 11": [        "force leader on regions: 435"      ]    }  },  {    "info": "Unsafe recovery enters demote Failed voter stage",    "time": "2024-04-08 16:58:44.664",    "actions": {      "store 1": [        "region 70 demotes peers { id:263 store_id:2 }, { id:296 store_id:3 }",        "region 351 demotes peers { id:353 store_id:2 }, { id:675 store_id:3 }",        "region 411 demotes peers { id:413 store_id:2 }, { id:680 store_id:3 }"      ],      "store 10": [        "region 30 demotes peers { id:264 store_id:2 }, { id:622 store_id:3 }"      ],      "store 11": [        "region 435 demotes peers { id:437 store_id:2 }, { id:438 store_id:3 }"      ]    }  },  {    "info": "Unsafe recovery Finished",    "time": "2024-04-08 16:58:55.671",    "details": [      "affected table ids: 40, 114, 137, 147, 152",      "no newly created empty regions"    ]  }]
复制代码


等待最后输出 "info": "Unsafe recovery Finished" ,即为恢复成功。



经查询,上述表可以进行访问。


(6) 检查数据索引一致性


即使表进行正常读写,但不代表数据没有丢失。


"affected table ids: 40, 114, 137, 147, 152", 恢复完受影响的表 id,我们根据表 id 进行查询:


SELECT TABLE_SCHEMA, TABLE_NAME, TIDB_TABLE_ID FROM INFORMATION_SCHEMA.TABLES WHERE TIDB_TABLE_ID IN (40, 114, 137, 147, 152);


现在我们上述进行检查:


admin check table 表名;
复制代码


若有不一致的索引,通过以下步骤进行修复:


  • 重命名索引:alter table 表名 rename 索引名 to 临时索引名

  • 创建新索引:alter table 表名 add index 索引名 (列名)

  • 删除旧索引:alter table 表名 drop index 临时索引名


(7) 宕机的节点下线


tiup cluster scale-in cluster-name -N IP2:20260,IP3:20260 --force
tiup cluster prune cluster-name
复制代码

3.3 V6.1.0 以上版本 (3 副本全部丢失)

经过在线有损恢复后,使用的感受非常良好。现在我们思考,如果 3 个副本全部丢失,是否可以使用这种方式来恢复我们的数据?


接下来一起测试下。


老方法,我们首先使用 tiup-bench prepare 数据:



集群 store 情况:


| id | address || – | ——- || 4 | IP2 || 1 | IP1 || 2 | IP7 || 10 | IP8 || 11 | IP9 |


Region 分布情况:



现在我们 mv 4,10,11 对应 TiKV 的 data 文件夹,并打开防火墙 (关闭和 pd 的通信) 以及中控机 tiup 的 ssh 端口模拟宕机。


#!/bin/bash
mv /data_dir /data_dir_delete
iptables -A OUTPUT -d pd_host1 -j DROP # (pd)iptables -A OUTPUT -d pd_host2 -j DROP # (pd)iptables -A OUTPUT -d pd_host3 -j DROP # (pd)iptables -A OUTPUT -d tiup_host -j DROP # (tiup)iptables -A INPUT -s pd_host1 -j DROP # (pd)iptables -A INPUT -s pd_host2 -j DROP # (pd)iptables -A INPUT -s pd_host3 -j DROP # (pd)iptables -A INPUT -s tiup_host -j DROP # (tiup)
复制代码


之后观察报错情况:


  • leader 和 region 节点监控消失,store size 为丢失了 3 副本




  • 业务异常,日志报错: “9005: Region is unavailable”



  • server report failure 出现错误报告



下面就到了激动人心的恢复时间了:


unsafe remove-faileds-stores 4,10,11
复制代码



unsafe remove-faileds-stores show
复制代码


最后一段输出信息:


 {    "info": "Unsafe recovery Finished",    "time": "2024-03-27 10:29:41.471",    "details": [      "affected table ids: 147, 152, 119, 10, 26, 36, 123, 125, 135, 14, 62, 96, 138, 88, 50, 120, 126, 46, 64, 105, 106, 130, 107, 48, 117, 118, 281474976710649, 40, 42, 76, 74, 24, 54, 68, 28, 129, 86, 124, 136, 144, 20, 82, 114, 113, 131, 16, 66, 90, 4, 112, 281474976710653, 143, 150, 142, 22, 56, 94, 111, 137, 6, 60, 92, 100, 34, 70, 281474976710652",      "newly created empty regions: 568, 562, 564, 572, 582, 560, 574, 576, 578, 566, 570, 580, 584"    ]  }
复制代码


查询结果:



结果是,在三副本全部丢失的情况下,恢复成功了,这就比较令我感到诧异,随后团队将这个现象反应给了官方,也期待之后进一步完善。

4. 总结及思考

一般情况下,当 TiDB 集群发生故障后,只需进行重启即可完成多数派的选举,使集群能够正常对外提供服务。


然而,在极端情况下,例如 SST 文件损坏,就需要使用有损恢复的方式进行数据恢复。在这种情况下,恢复方案需要经过反复验证,以确保在线上的极端情况下能够成功完成数据恢复。


本文主要以 V6.1.0 为分界,针对 V6.1.0 版本及其之前和之后的两个版本,在 3 副本状态下多副本丢失的场景下进行故障模拟,并分别使用 tikv-ctl 手动恢复和在线有损恢复两种方式进行数据恢复。


值得注意的是,V6.1.0 之前的版本在线有损恢复功能为实验特性,因此对于小于 V6.1.0 的集群,我们可以考虑使用 tikv-ctl 手动恢复;而对于版本大于 V6.1.0 的集群,我们则可以考虑使用在线有损恢复方式。


同时,如果能够将恢复过程自动化,将极大地提高业务的稳定性。


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

TiDB 社区官网:https://tidb.net/ 2021-12-15 加入

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

评论

发布
暂无评论
TiDB多数派节点故障恢复指南_实践案例_TiDB 社区干货传送门_InfoQ写作社区