写点什么

TiKV 多副本丢失以及修复实践

  • 2022 年 7 月 11 日
  • 本文字数:6380 字

    阅读完需:约 21 分钟

作者: Meditator 原文来源:https://tidb.net/blog/ad45bad9


是否首发:首发


正文

1 实验目的

随着 tidb 使用场景的越来越多,接入的业务越来越重要,不由得想试验下 tidb 组件的高可用性以及故障或者灾难如何恢复,恢复主要涉及的是 pd 组件和 tikv 组件,本文主要涉及 tikv 组件,


pd 组件请参考另外一篇文章《pd 集群多副本数据丢失以及修复实践》pd 集群多副本数据丢失以及修复实践

2 试验环境

2.1 版本以及部署拓扑:

tidb 版本:5.2.1


部署方式:tiup


部署拓扑


$ cat tidb-test.yamlglobal:  user: "tidb"  ssh_port: 22  deploy_dir: "/data/tidb/tidb-deploy"  data_dir: "/data/tidb/tidb-data"
pd_servers: - host: 10.12.16.225 - host: 10.12.16.226 - host: 10.12.16.227
tidb_servers: - host: 10.12.16.225 - host: 10.12.16.226 - host: 10.12.16.227
tikv_servers: - host: 10.12.16.224 - host: 10.12.16.225 - host: 10.12.16.226 - host: 10.12.16.227 - host: 10.12.16.228
monitoring_servers: - host: 10.12.16.228
grafana_servers: - host: 10.12.16.228
alertmanager_servers: - host: 10.12.16.228
复制代码



5*TIKV


replica=3

温馨提示:

防止 tiup 部署后,在破坏掉 tikv 实例后,tikv-server 被自动拉起来,影响试验效果,需要做如下修改


1、在 /etc/systemd/system/tikv-20160.service 中去掉 Restart=always 或者改 Restart=no,


2、执行 systemctl daemon-reload 重新加载

2.2 查看测试表数据

CREATE TABLE `t_test` (  `name` varchar(200) DEFAULT '',  `honor` varchar(200) DEFAULT '') ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T! SHARD_ROW_ID_BITS=4 PRE_SPLIT_REGIONS=4 */
mysql> desc t_test;+-------+--------------+------+------+---------+-------+| Field | Type | Null | Key | Default | Extra |+-------+--------------+------+------+---------+-------+| name | varchar(200) | YES | | | || honor | varchar(200) | YES | | | |+-------+--------------+------+------+---------+-------+2 rows in set (0.00 sec)
mysql> select count(*) from t_test;+----------+| count(*) |+----------+| 1024288 |+----------+1 row in set (3.68 sec)
复制代码

3 单副本损毁及修复

过程略


提示:


此种场景也是最常见的场景,replica>=3 的时候,不会影响业务读写,也不会丢失数据,只需要扩容新 TiKV 节点,缩容下线故障节点即可。


如果是 3*TiKV 集群,必须只能先扩容,否则此时即便强制缩容下线故障节点,数据也不会发生 replica 均衡调度,因为无法补齐三副本。

4 双副本同时损毁及修复

4.1 查看测试表 region 分布


mysql> select STORE_ID,ADDRESS,LEADER_COUNT,REGION_COUNT from information_schema.TIKV_STORE_STATUS ;+----------+--------------------+--------------+--------------+| STORE_ID | ADDRESS            | LEADER_COUNT | REGION_COUNT |+----------+--------------------+--------------+--------------+|        1 | 10.12.16.228:20160 |           12 |           25 ||        2 | 10.12.16.225:20160 |           11 |           33 ||        4 | 10.12.16.226:20160 |            9 |           14 ||        3 | 10.12.16.227:20160 |            6 |           38 ||        9 | 10.12.16.224:20160 |            7 |           25 |+----------+--------------------+--------------+--------------+5 rows in set (0.01 sec)
复制代码



4.2 模拟 2 个 tikv 同时损坏

同时损坏的 TiKV 节点是 10.12.16.227:20160 和 10.12.16.228:20160


在 10.12.16.227(store_id=3)和 10.12.16.228(store_id=1)上分别执行



$ cd /data/tidb/tidb-data/$ lsmonitor-9100 pd-2379 tikv-20160$ rm -rf tikv-20160$ lsmonitor-9100 pd-2379
复制代码


查看集群状态:



查看 store_id=3 和 store_id=1 的状态:



可以发现 30 分钟过后(store 的状态从 disconnecting–》down),store 1 和 3 上的 region 的 leader 和 replica 还存在,并不是因为 store 是 down 状态,其上面的 regionleader 和 replica 进行切换和调度,那是因为部分 region 同时失去两个副本,导致无法发生 leader 选举。


mysql> select count(*) from t_test;
ERROR 9002 (HY000): TiKV server timeout
复制代码



tidb 查询发现 hang 住直到超时

4.3 修复 tidb 集群

4.3.1 关闭调度

关闭调度原因:防止恢复期间出现其他的异常情况


关闭调度方法:config set region-schedule-limit、replica-schedule-limit、leader-schedule-limit、merge-schedule-limit 这 4 个值


» config set region-schedule-limit 0» config set replica-schedule-limit 0» config set leader-schedule-limit 0» config set merge-schedule-limit 0
复制代码
4.3.2 查询出大多数副本在故障 tikv 上的 region id

检查大于等于一半副本数在故障节点(store_id in(1,3))上的 region,并记录它们的 region id


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


4.3.3 关闭正常的 tikv 节点
$ tiup cluster stop    tidb-test  -N 10.12.16.224:20160$ tiup cluster stop    tidb-test  -N 10.12.16.225:20160$ tiup cluster stop    tidb-test  -N 10.12.16.226:20160
复制代码


4.3.4 清理故障 store 的 region

清理方法:


在正常的 tikv(已经关闭掉)上执行命令:


$ ./tikv-ctl --data-dir /data/tidb/tidb-data/tikv-20160 unsafe-recover remove-fail-stores -s 1,3 --all-regions
复制代码


执行命令在输出的结尾有 success 字样,说明执行成功


清理原因:在正常 tikv 上清理掉 region peer 落在故障 tikv(1 和 3)peer

4.3.5 重启 pd 集群
$ tiup cluster restart    tidb-test  -R pd
复制代码


查看 store 1 和 store 3



发现上面的 leader_count 和 region_count 都变成 0,如果 pd 集群不重启,则不会消失。

4.3.6 启动正常的 tikv 节点
$ tiup cluster start    tidb-test  -N 10.12.16.224:20160$ tiup cluster start    tidb-test  -N 10.12.16.225:20160$ tiup cluster start    tidb-test  -N 10.12.16.226:20160
复制代码



查看副本数为 2 的 region:


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


{"id":36,"peer_stores":[2,9]}{"id":140,"peer_stores":[2,9]}{"id":249,"peer_stores":[2,4]}{"id":46,"peer_stores":[2,9]}{"id":168,"peer_stores":[2,9]}{"id":176,"peer_stores":[2,9]}{"id":188,"peer_stores":[4,9]}{"id":48,"peer_stores":[9,2]}{"id":184,"peer_stores":[2,9]}{"id":26,"peer_stores":[2,9]}{"id":152,"peer_stores":[4,2]}{"id":52,"peer_stores":[2,4]}{"id":40,"peer_stores":[4,2]}{"id":253,"peer_stores":[4,9]}{"id":44,"peer_stores":[2,9]}
复制代码


查看只有单副本的 region:


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


{"id":42,"peer_stores":[2]}{"id":62,"peer_stores":[9]}{"id":192,"peer_stores":[9]}{"id":180,"peer_stores":[2]}{"id":196,"peer_stores":[2]}{"id":60,"peer_stores":[9]}{"id":160,"peer_stores":[2]}{"id":164,"peer_stores":[4]}{"id":54,"peer_stores":[9]}{"id":172,"peer_stores":[2]}{"id":220,"peer_stores":[2]}{"id":7,"peer_stores":[9]}{"id":50,"peer_stores":[9]}{"id":144,"peer_stores":[9]}{"id":156,"peer_stores":[2]}{"id":38,"peer_stores":[2]}{"id":56,"peer_stores":[2]}
复制代码
4.3.7 打开调度
config set region-schedule-limit  2048config set replica-schedule-limit 64config set leader-schedule-limit  4config set merge-schedule-limit   8
复制代码
4.3.8 验证数据
$ ./pd-ctl region --jq='.regions[] | {id: .id, peer_stores: [.peers[].store_id] | select(length as $total |map(if .==(1,3) then . else empty end)|length>=$total-length)}'  
复制代码


输出为空



数据已经可以查询,并且数据没有丢失


查看只有单副本的 region:



查看副本数为 2 的 region:


4.3.9 清理收尾

发现 store 1 和 3 还是存在(状态为 Down),需要在集群中剔除掉



删除掉 store 1 和 3


» store delete 1Success!» store delete 3Success!
复制代码




$ tiup cluster prune tidb-test
复制代码


$ tiup cluster display tidb-test
复制代码



发现 227 和 228 已经不在集群


至此,双副本同时丢失的情景已经修复完毕

5 三副本同时损毁及修复

5.1 查看测试表 region 分布

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


{"id":220,"peer_stores":[2,9,497041]}{"id":249,"peer_stores":[2,4,497042]}{"id":7,"peer_stores":[9,497041,497042]}{"id":36,"peer_stores":[2,9,497041]}{"id":140,"peer_stores":[2,497042,497041]}{"id":144,"peer_stores":[9,497042,2]}{"id":156,"peer_stores":[2,4,497042]}{"id":168,"peer_stores":[2,9,497042]}{"id":176,"peer_stores":[2,497042,4]}{"id":188,"peer_stores":[497042,9,497041]}{"id":38,"peer_stores":[2,9,497041]}{"id":46,"peer_stores":[9,2,497041]}{"id":50,"peer_stores":[9,497041,497042]}{"id":48,"peer_stores":[2,9,497041]}{"id":56,"peer_stores":[9,497041,497042]}{"id":184,"peer_stores":[2,9,497041]}{"id":152,"peer_stores":[4,9,497041]}{"id":192,"peer_stores":[9,497042,497041]}{"id":26,"peer_stores":[497042,497041,2]}{"id":42,"peer_stores":[2,9,497042]}{"id":62,"peer_stores":[9,497041,497042]}{"id":180,"peer_stores":[2,9,497042]}{"id":196,"peer_stores":[2,497041,497042]}{"id":22,"peer_stores":[4,497042,9]}{"id":52,"peer_stores":[4,497042,9]}{"id":148,"peer_stores":[4,9,497041]}{"id":40,"peer_stores":[4,9,497042]}{"id":160,"peer_stores":[2,9,497041]}{"id":164,"peer_stores":[4,497041,497042]}{"id":253,"peer_stores":[4,2,497042]}{"id":257,"peer_stores":[4,9,497041]}{"id":34,"peer_stores":[4,497041,497042]}{"id":58,"peer_stores":[4,497042,9]}{"id":60,"peer_stores":[9,497041,497042]}{"id":44,"peer_stores":[2,9,497041]}{"id":54,"peer_stores":[9,497041,497042]}{"id":172,"peer_stores":[497041,9,497042]}
复制代码


mysql> select count(*) from t_test;+----------+| count(*) |+----------+|  1024288 |+----------+1 row in set (0.14 sec)
mysql> select count(*) from t_test;
+----------+
| count(*) |
+----------+
| 1024288 |
+----------+
1 row in set (0.14 sec)
复制代码

5.2 模拟 3 个(所有副本)tikv 同时损坏

模拟 10.12.16.226:20160 10.12.16.227:20160 10.12.16.228:20160 三个 tikv 节点同时挂掉


在 226、227、228 上执行:



$ cd /data/tidb/tidb-data$ lsmonitor-9100 pd-2379 tikv-20160$ rm -rf tikv-20160$ lsmonitor-9100 pd-2379
复制代码


查看集群状态:


$ tiup cluster display tidb-test
复制代码


5.3 修复 tidb 集群

5.3.1 关闭调度
config set region-schedule-limit 0config set replica-schedule-limit 0config set leader-schedule-limit 0config set merge-schedule-limit 0
复制代码
5.3.2 查询出三个(所有)副本在故障 tikv 上的 region id
mysql> select STORE_ID,ADDRESS,LEADER_COUNT,REGION_COUNT,STORE_STATE_NAME from information_schema.TIKV_STORE_STATUS order by STORE_STATE_NAME;+----------+--------------------+--------------+--------------+------------------+| STORE_ID | ADDRESS            | LEADER_COUNT | REGION_COUNT | STORE_STATE_NAME |+----------+--------------------+--------------+--------------+------------------+|   497041 | 10.12.16.228:20160 |            2 |           25 | Disconnected     ||   497042 | 10.12.16.227:20160 |            2 |           26 | Disconnected     ||        4 | 10.12.16.226:20160 |           12 |           13 | Disconnected     ||        2 | 10.12.16.225:20160 |           11 |           19 | Up               ||        9 | 10.12.16.224:20160 |           10 |           28 | Up               |+----------+--------------------+--------------+--------------+------------------+5 rows in set (0.00 sec)
复制代码


5.3.3 关闭正常的 tikv 节点
$ tiup cluster stop    tidb-test  -N 10.12.16.224:20160$ tiup cluster stop    tidb-test  -N 10.12.16.225:20160$ tiup cluster display    tidb-test
复制代码


5.3.4 清理故障 store 的 region

清理方法:


在正常的 tikv(已经关闭掉)上执行命令:


$ ./tikv-ctl --data-dir /data/tidb/tidb-data/tikv-20160 unsafe-recover remove-fail-stores -s 4,497041,497042 --all-regions
复制代码


执行命令在输出的结尾有 success 字样,说明执行成功


清理原因:在正常 tikv 上清理掉 region peer 落在故障 tikv(4,497041,497042)peer

5.3.5 重启 pd 集群
$ tiup cluster restart    tidb-test  -R pd
复制代码
5.3.6 启动正常的 tikv 节点
$ tiup cluster start    tidb-test  -N 10.12.16.224:20160$ tiup cluster start    tidb-test  -N 10.12.16.225:20160$ tiup cluster display    tidb-test  
复制代码


5.3.7 打开调度
config set region-schedule-limit  2048config set replica-schedule-limit 64config set leader-schedule-limit  4config set merge-schedule-limit   8
复制代码
5.3.8 验证数据


mysql> select count(*) from t_test;
ERROR 9005 (HY000): Region is unavailable
复制代码


5.3.9 补偿所有副本都丢失的 region

5.3.9.1 查询所有副本都丢失的 region,并记录 region id


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


{"id":164,"peer_stores":[4,497041,497042]}
复制代码



5.3.9.2 停止实例


停止 10.12.16.225:20160 tikv 实例(可以是其他任意正常的 tikv 实例)


5.3.9.3 根据上面查询出丢失的 region id 创建空 region


$ ./tikv-ctl --data-dir /data/tidb/tidb-data/tikv-20160 recreate-region -p 127.0.0.1:2379 -r 164
复制代码


命令输出结尾有 success 字样,说明创建成功


5.3.9.4 验证数据



原来总数为 1024288,发现数据有丢失

5.3.10 收尾
$ tiup cluster display    tidb-test 
复制代码



» store delete 4Success!» store delete 497041Success!» store delete 497042Success!
复制代码


如果通过 tiup cluster display tidb-test 执行命令发现 226、227、228 上的 store 状态为 up,说明开启了自动拉起


$ tiup cluster prune tidb-test
复制代码

6 总结

1、如果 region 的单个副本丢失(小于 replica 一半的情况下),集群是不会丢失数据,此场景是绝大多数用户 tikv 挂掉场景;


2、如果 region 多副本(副本数大于 replica/2)丢失,如果开启 sync-log=true 则不会丢失数据,否则可能会丢失数据;


3、如果 region 所有副本丢失,此时必定会丢失数据,需要进行破坏性修复;


4、如果单机多 tikv 实例部署,一定需要打 label,否则主机挂掉,region 的多副本或者全部副本可能会丢失,从而导致丢失数据;


发布于: 13 分钟前阅读数: 2
用户头像

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

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

评论

发布
暂无评论
TiKV 多副本丢失以及修复实践_实践案例_TiDB 社区干货传送门_InfoQ写作社区