TiKV 状态变化
作者: knull 原文来源:https://tidb.net/blog/1b199f3b
背景说明
1、store 状态
是什么?
首先,这里说的
状态
,是store
的状态。即,这里不谈 region 的状态。其次,这里的
store
,可以简单类比为 TiKV 节点。最后,这个
状态
是指整个集群中的store 状态
,存储在 PD(ETCD) 中的状态(可能跟 store 真实状态有偏差、不一致)。
分布式集群节点状态,是通过心跳来判断的。心跳依赖网络,所以网络异常导致无法准确判断节点状态。但是,心跳可以展示“正常”状态。
同样的,我们 TiKV 集群的 TiKV(Store) 节点状态也是通过心跳判断,存储在 PD(ETCD),有 PD 负责维护。而状态展示也是 PD(ETCD) 中的数据 —— 注意,并不是直接去取节点的实际状态。
分布式集群、状态等是个很大的话题,这里简单说明下,方便后续内容理解
2、工具使用
既然研究 Store 状态
,必然需要经常查看,即需要查询 PD(ETCD) 存储的数据。我们这里有两个工具可以使用
2.1、etcdctl
这个是 etcd 本身直接提供的查询工具。我们这里需要用的命令如下:
ETCDCTL_API: 指定 etcd 的 api 版本。一般用 3(还有就是 2)
etcdctl:这个是 etcd 的工具,可以通过 tiup 安装:
tiup ctl:$(version) etcd get
。版本不重要,因为 etcd 一般不会经常变
endpoints:访问的 api 接口的地址。一般就是 pd 的访问地址(比如 dashboard)
get:表示要做的事情。我们这里的测试,get 就够了。
“/pd/”:表示要取的数据的“目录”
Etcd 一般以类似目录格式存放 key。
比如 “/” 下可以有多组 key,下一层可以是 pd 可以是 cluster。
说不清楚,试试就明白了。
prefix:表示是否是前缀。
即 如果这个设置为 false,那么表示完整的 key 取查询。
如果设置为 true,那么表示前缀。比如这里的 “/pd/ ”,表示取 “/pd/*”,或者说取 pd 目录下的索引 key
另外,如果设置为 true,是递归访问的。比如这里的 “/pd/“,那么 pd 下有还有 目录 x,那么就会继续遍历 目录 x
2.2、pd-ctl
这个本质也是访问 etcd 中存储的数据。但是,稍微做了一层封装:从 etcd 中取出来的数据,经过处理、组装之后,再返回给客户展示。
我们这里主要查看 store 相关数据。所以,命令主要如下:
store 后面可以带的字命令:[delete | cancel-delete | label | weight | remove-tombstone | limit ] <store_id> [–jq=”<query string>“]
这里是 官方文档参考
2.3、直接通过 pd 的 api 查询
这个可以到 dashboard 上查看 “高级调试 -> 内部调试数据” 查看具体的 API。这里,store 相关的 api 如下:
理论说明
关于store 状态
相关,可以参考这里 官方文档。这里有部分说明。
各种状态
store 状态
有如下 5 种状态。这是从官方文档摘录。
Up:表示当前的 TiKV Store 处于提供服务的状态。
Disconnect:当 PD 和 TiKV Store 的心跳信息丢失超过 20 秒后,该 Store 的状态会变为
Disconnect
状态。Down:当 PD 和 TiKV Store 的心跳信息丢失超过 30 分钟后,该 Store 的状态会变为
Down
状态,Offline:当对某个 TiKV Store 通过 PD Control 进行手动下线操作,该 Store 会变为 Offline 状态。
pd-ctl store delete
该状态只是 Store 下线的中间状态,处于该状态的 Store 会将其上的所有 Region 搬离至其它满足搬迁条件的 Up 状态 Store。
这个是 PD 发现 store 是 offline,就会触发调度搬迁 region。
Tombstone:当该 Store 的
leader_count
和region_count
为 0 后,该 Store 变为 Tombstone 状态。可以使用
remove-tombstone
接口安全地清理该状态的 TiKV。
“搬迁 region” 到底是做啥事情、动作?是先 add peer,然后再 remove peer ?一个 region,怎么才算搬迁成功?
如果部分 region 无法完成搬迁,会一直是 offline 状态。那么,应该怎么处理?
综述:
我个人理解,状态可以分为两类:
间接状态:需要通过心跳来判定、转换的状态。
包括
Disconnected
和Down
。直接状态:记录存储到 PD(ETCD) 中的。
在正常情况下(即没有丢失状态),那么直接查询到直接展示的状态。包括 UP/Offline/Tombstone
各种状态切换
下图是官方文档上的。
下图是获取 store 状态的时候的源码截图 (点这里查看源码)。大约情况是:
获取原始数据状态
如果状态是 UP,根据 最后一次心跳做判断
根据状态转换和源码截图,可以得到如下信息:
如果离最后一次心跳超过 20s(不到 30 分钟),那么就是
Disconnected
如果离最后一次心跳超过 30 分钟,就是
Down
即,如果 stop 了 TiKV 节点,那么该 TiKV 在 30 分钟以内也是
Disconnected
并且,如果 stop 之后 20s 以内查看 TiKV 状态,应该是
Up
状态。如果用户执行了 store delete,那么就是 Offline
即,表示要把该节点从 集群中剔除。
但是,还有数据要搬迁(可以类比为“离职员工交接”)。
所以,该状态是中间状态 —— 是要把事情处理完了(搬迁完了),才能走。
如果 Offline 节点的数据搬迁完了,那么就可以转成 Tombstone。
搬迁完,即 leader 和 region count 都是 0.
数据搬迁完了(交接完了),那么可以退出集群了——即,该集群不会再跟该节点联系了。
可以人工去删除数据。
那么,正常情况下,就是 UP 状态咯。
除了上述异常情况,那么就是正常情况咯。
各种状态会带来什么
如下截图,据说后续会改成 NodeState,很好的反应出要做啥事情。
UP:这种状态下,可以对外提供服务。不会做其它额外的事情。
Disconnected:好像不会做啥事情(?)
注意,这会导致 region 的 leader 重新选举,导致业务性能下降一波。
Down:这种情况下,会对该 store 上的 region 进行
补副本
。注意,是max-store-down-time 来控制的,在变成 down ,之后会任务改 store 不可用,会对 该 store 上的 region 补副本。
Offline:这种情况下,需要对该 store 上的 region 进行
迁移
。迁移的意思是
补副本
+删除 该 store 上的 副本
—— 这里的“删除”,可以仅仅是 PD 中的信息删除。看 NodeState 可以知道,它是正在删除 region 过程中,所以是 Removing。。。
TombStone:这种情况下,与集群没有关系了,所以该节点做啥都无所谓咯。
测试说明
初始化状态
刚刚部署好的集群,仅仅启动 PD ,集群中 store 是啥状态?
1、通过 etcdctl 查看,可以知道没有 store 相关数据。
2、通过 pd-ctl 查看,是报 500 的错误 —— 应该是因为没有数据导致的。
3、通过 tiup 查看集群状态,可以看到 TiKV 节点都是 Down 状态
启动之后状态
基于上面情况,启动整个集群之后,状态如下
stop 之后状态(stop -R tikv)
1、立马查看:理论上说是 UP 状态
2、20 秒之后查看:理论上说是 Disconnected(持续 30 分钟)
3、30 分钟之后查看:理论上说是 Down
4、删除 Store(scale-in)
实际案例
案例 1
当前状态
当前 tikv 是 offline,并且无法正常启动。offline 表示已经不在集群中了。而 offline 会导致 region、leader 迁移到其它 tikv 节点。
当前问题
由于是单副本,即 tikv-3 的 region 只有 tikv-3 有,其它 tikv 是没有的。由于 tikv-3 无法正常启动,所以无法把 region 迁移出去,所以无法完成 offline,导致一直卡在这里、恢复正常。
解决问题
可以考虑想办法把 tikv-3 正常启动 —— 这个比较难,如果可以的话,也不会让其下线了。
只能丢失数据,放弃 tikv-3 上的 region。在其它 tikv 上补上这个 9 个 region(空的)
查看 tikv-3 所有 region,然后执行命令 ”tikv-ctl –db /path/to/tikv-data/db recreate-region –pd <endpoint> -r <region_id>”
可惜,执行这个操作之后,是没有效果的(报错)
只能重建集群了(还好是测试环境)
案例 2
背景情况:
最后心跳时间是 14:30 左右
当前状态是 Down
region/leader count 是 0
查询时间大约在 21:30 +5:30 左右
集群是 k8s 集群,在没有人为操作的情况下,在 23:30 +5:30 左右变成了 tombstone
理论上来说,需要执行 “delete”使其状态变成 offline,然后 region/leader count 为 0 则可以切换为 tombstone。
但是,在至少 2 个小时 Down 中都没有变化,突然就变成了 tombstone。
不了解 k8s 的自动切换的原理 —— 即原来的 store 4 由于启动不了,所以替换为了 store xxxx,但是仍然是 tikv-1 实例。
另外,怀疑是客户手动 delete 了 pod ?
案例 3
由于 compaction 导致某个磁盘空间突然飞涨,导致无法启动、运行。
Workaround :磁盘扩容。
案例 4
情况汇总: 初始情况:
客户 1pd + 3tidb + 3tikv(tikv0<store1>/tikv1/tikv2);
第一阶段
由于 pv 扩容, rollout 导致多了个 pod 运行 tikv0(store-n);现在 store1 和 store-n 同时存在;
store-1 是有问题,本身启动不了,Down 了;
客户执行了 pd-ctl delete store-0 ,但是删除失败
store-n 和 store-1 都用 tikv-0 的地址,所以导致 store-n 注册 pd 失败启动不了;
第二阶段:
由于 autofailover,导致自动扩容了 tikv-3;
但是由于资源不够导致 挂起;
客户有发现之后,就手动吧 tikv-3 scale-in 了;导致现在的 tikv-3 也是 down 状态
要恢复集群,就是不不正常的 store 剔除
、让正常的 store 启动起来
。
不正常的 store-1,是因为还有 region 残留,可以直接通过 remove peer 来达到清零的效果(有三副本,所以删除了系统自动会补副本)。
正常的 store-n 启动起来。原来无法启动,是因为 store-1 占用了 tikv0 的实例(address),导致无法启动。那么,store-1 正常剔除之后,自然就启动正常了。
MoreAndMore:k8s(operators)
一开始打算的时候,没想研究这个:因为太复杂,完全不懂。
但是,在分析案例的时候,发现这几个问题或多或少都跟 k8s 相关:如果是 OP 环境,很容易就知道怎么玩了,但是 k8s 环境就完全不知道。所以,k8s 就自然而然的要研究下。
Restart pod
在 OP 环境,如果 tidb 异常重启(比如 OOM),那么就是进程变化而已。那么,在 k8s 环境,如果 tidb OOM ,会发生什么呢?
本质上来说,Pod 也是一个进程。所以,发生重启的话,Pod 变化了(进程 变了),但是其它都没变(磁盘、配置等),所以 tikv(store) 节点是都没有变化的。
Autofailover
Autofailover 本质上来说,就是 scale-out + scale-in ,即
异常 Pod 缩容
扩容一个新的正常 Pod 来代替
MoreAndMore:offline 迁移到底做了啥
Offline 状态下的迁移 region,主要做了如下事情:
先 transfer leader 到非 offline 的节点
然后 replica 一个 peer,
最后 remove offline 的那个 peer
即,这个过程是跟 offline 的 tikv 无关的,不需要对 offline 的 tikv 做交互。
Transfer leader 是 raft 协议保证的
Replica 是从 leader 来做的——但是 leader 不在 offline 的 tikv
remove offline 的那个 peer,是删除 pd 中的记录就可以了
参考
版权声明: 本文为 InfoQ 作者【TiDB 社区干货传送门】的原创文章。
原文链接:【http://xie.infoq.cn/article/c24e5e79bec7f79bd33dcb41a】。文章转载请联系作者。
评论