TiDB 集群的可用性详解及 TiKV Label 规划

TiDB 集群的可用性详解及 TiKV Label 规划,第1张

目录

一、前言

二、TiDB 集群核心组件可用性概览

1. TiDB Server 的可用性

三、Multi-Raft 集群的可用性限制

1. Raft 简介

2. Raft Group 副本数的选择

3. PD 是单一 Raft Group

4. TiKV 是 Multi-Raft 系统

5. Multi-Raft 集群的可用性限制

四、规划 TiKV Label 以提升 TiKV 集群的可用性

1. TiKV Label 简介

2. Label 相关的 PD 调度策略解读

3. TiKV Label 的规划

4. 使用 Label 的注意事项

五、典型两地三中心跨中心高可用多活容灾备配置

1. 物理服务器主机配置

2. 服务器,机柜,机房,网络要求

3. 两地三中心集群的扩容策略

分布式系统的核心理念是让多台服务器协同工作,完成单台服务器无法处理的任务。单点的硬件和网络等都是不可靠的,想要提高硬件的可靠性需要付出大量的成本,因此分布式系统往往通过软件来实现对于硬件的容错,通过软件来保证整体系统的高可靠性。

TiDB 集群中包含了串-并联系统,表决系统等,相对于一般的分布式系统更为复杂,TiDB 中所保存的数据的可用性由诸多因素控制,通过本篇文章的介绍,您可以了解到怎样在给定的资源下设计部署架构以尽可能地提高数据的可用性。

在 TiDB 集群的三个核心组件 PD,TiKV,TiDB 中,PD 和 TiKV 都采用 Raft 协议实现持久化数据的容灾以及自动的故障转移,有关 PD 和 TiKV 的可用性的详细解读,请参见第三章的内容。

TiDB Server 组件不涉及数据的持久化,因此 TiDB 被设计成了无状态的,TiDB 进程可以在任意位置被启动,多个 TiDB 之间的关系是对等的,并发的事务通过同一台 TiDB 发送给集群和通过多台 TiDB 发送给集群所表现的行为完全一致。单一 TiDB 的故障只会影响这个 TiDB 上当前的连接,对其他 TiDB 上的连接没有任何影响。

根据用户最佳实践,在 TiDB 之上一般会部署负载均衡器(F5,LVS,HAproxy,Nginx 等),因此负载均衡器所连接的 TiDB 越多,其整体可用性就越高,其整体所能承载的并发请求数量也越多。

在使用负载均衡器的场景下,建议使用的负载均衡算法为 least connection,当某个 TiDB 发生故障依然会导致当时连接到该 TiDB 上的请求失败,负载均衡器识别到 TiDB 的故障之后,将不再向此 TiDB 建立新的连接,而是将新的连接建立到可用的 TiDB 上,以此来实现整体的高可用。

Raft 是一种分布式一致性算法,在 TiDB 集群的多种组件中,PD 和 TiKV 都通过 Raft 实现了数据的容灾。Raft 的灾难恢复能力通过如下机制实现:

Raft 算法本身以及 TiDB 中的 Raft 实现都没有限制一个 Raft Group 的副本数,这个副本数可以为任意正整数,当副本数为 n 的时候,一个 Raft Group 的可靠性如下:

我们一般建议将 Raft Group 的副本数设置为奇数,其原因如下:

在一般的非关键业务场景下,建议将副本数选为 3;而在关键业务中建议将副本数选为 5。

遵循 Raft 可靠性的特点,放到现实场景中:

PD 集群只包含一个 Raft Group,即 PD 集群中 PD 服务的个数决定了 PD 的副本数,3 PD 节点集群的 PD 副本数为 3,5 PD 节点集群的 PD 副本数为 5。

由上一段落中 Raft 原理可知,一个 Raft Group 的容灾能力随节点数增加而加强,在一般的非关键业务场景下,建议部署 3 个 PD;建议在关键业务中部署 5 个 PD。

TiKV 是一个 Key-Value 存储系统,它是一个巨大的 Map,TiKV 提供有序遍历方法。下图展示了 region 以 3 副本模式存储在 4 台 TiKV 节点上的数据分布,TiKV 中的数据被切分成了 5 份 —— region 1~5,每个 region 的 3 个副本构成了一个 Raft Group,集群中共有 5 个 Raft Group,因此 TiKV 是 Multi-Raft 系统。

如上图所展示,虽然这个集群当前有 4 个 TiKV 实例,但一个 region 的 3 个副本只会被调度到其中 3 个 TiKV 上,也就是说 region 的副本数与 TiKV 实例数量无关,即使将上图的集群扩容到 1000 个 TiKV 实例,它也仍然是一个 3 副本的集群。

前面说到 3 副本的 Raft Group 只能容忍 1 副本故障,当上图的集群被扩容到 1000 个 TiKV 实例时,这个集群依然只能容忍一个 TiKV 实例的故障,2 个 TiKV 实例的故障可能会导致某些 region 丢失多个副本,整个集群的数据也不再完整,访问到这些 region 上的数据的 SQL 请求将会失败。

而 1000 个 TiKV 中同时有两个发生故障的概率是远远高于 3 个 TiKV 中同时有两个发生故障的概率的,也就是说 Multi-Raft 集群在逐步扩容中,其可用性是逐渐降低的。

TiKV Label 用于描述 TiKV 的位置信息,在 inventory.ini 中,其写法如下:

上面案例中规划了 4 层位置信息的 Label,Label 信息会随着 deploy.yml 或 rolling_update.yml 操作刷新到 TiKV 的启动配置文件中,启动后的 TiKV 会将自己最新的 Label 信息上报给 PD,PD 根据用户登记的 Label 名称(也就是 Label 元信息),结合 TiKV 的拓扑进行 region 副本的最优调度。用户可以根据自己的需要来定制 Label 名称,以及 Label 层级(注意层级有先后顺序),但需要注意 PD 会根据它读到的 Label 名称(含层级关系)去匹配 TiKV 的位置信息,如果 PD 读到的 TiKV Label 信息与 PD 中设置的 Label 名称不匹配的话,就不会按用户设定的方式进行副本调度。Label 名称的设置方法如下,在初次启动集群时,PD 会读取 inventory.ini 中的设置:

非初次启动的集群,需要使用 pd-ctl 工具进行 Label 名称设置:

从本质上来说,Label 系统是一种 PD 对 region 副本(replica)的隔离调度策略。

PD 首先读取到集群的 region 副本数信息*,假定副本数为 5。PD 将所有 TiKV 汇报给它的 Label 信息进行汇总(以本章第 1 小节的 TiKV 集群为例),PD 构建了整个 TiKV 集群的拓扑,其逻辑如下图所示:

PD 识别到第一层 Label - dc 有 3 个不同的值,无法在本层实现 5 副本的隔离。PD 进而判断第二层 Label - zone,本层有 z1~z5 这 5 个 zone,可以实现 5 副本的隔离调度,PD 会将各个 region 的 5 个副本依次调度到 z1~z5 中,因此 z1~z5 各自所对应的 4 个 TiKV 所承载的 region 数量总和应完全一致。此时,PD 的常规调度策略,如 balance-region,hot-region 等 region 相关的 scheduler 将严格遵守 Label 的隔离策略进行调度,在带有 z1~z5 Label 信息的 TiKV 尚在的情况下不会将同一个 region 的多个副本调度到同一个 zone 中。如图,图中将 TiKV 按照 zone 做 4 个一组隔离开了,一个 region 的一个副本只会在本 zone 的 4 个 TiKV 之间调度。

PD 天生不会将同一个 region 的多个副本调度到同一个 TiKV 实例上,增加 Label 信息后,PD 不会将同一个 region 的多个副本调度到同一个 host 上,以避免单台服务器的宕机导致丢失多个副本。

当带有某一个 zone Label 的 TiKV 全部故障时,如图中所有带有 z5 Label 的几个 TiKV 实例 kv252-1,kv252-2,kv253-1,kv253-2 同时故障时,集群会进入缺失一个副本的状态,在达到 TiKV 最大离线时间的设置值(max-store-down-time,默认值 30min)之后,PD 便开始在其他 4 个 zone 中补全所有缺失副本的 region,同时遵循上面一段所提到的约束,在为 region1 补全副本时,PD 会避开所有包含 region1 的服务器(本例中的 host)h208,h210,h414,h416 所涉及的 8 个 TiKV 实例,而在另外 8 个 TiKV 实例中挑选一个进行副本补全调度。

*副本数设置方法如下,以 5 副本为例:

Label 登记的是 TiKV 的物理位置信息,PD 根据 TiKV 的物理位置进行最优调度,其目的是在具有相近物理位置的 TiKV 上只放置一个副本,以尽可能的提高 TiKV 集群的可用性。举个例子,假设某一时刻集群中一定要有两个 TiKV 同时发生故障,那么你一定不想它们上面存储着一个 region 的两个副本,而通过合理规划让同时故障的两个 TiKV 出现在同一个隔离区的概率变高,TiKV 集群的整体可用性也就越高。因此 Label 规划要与 TiKV 物理位置规划一起进行,两者是相辅相成的。

举例而言,机房可能会由于电源故障,空调故障,网络故障,火灾,自然灾害等原因而整体不可用;机柜可能由于交换机故障,UPS 故障,消防喷淋等原因而整体不可用;服务器可能由于常见的内存等故障而宕机。通过妥善的 Label 规划,使 region 调度按物理位置进行隔离,可以有效地降低一个区域故障造成的整体影响。

物理位置的层级结构一般为机房,机柜,服务器,在大型基础设施中还会在机房与机柜之间多一个楼层信息。设计 Label 层级结构的最佳实践是基于物理层级结构再加上一层逻辑层级,该逻辑层级专门用于控制保持与集群副本数一致,在本案例中,zone 就是逻辑层级,该层级的值在集群搭建初期与 rack 保持一一对应,用于控制副本的隔离。而不直接采用 dc,rack,host 三层 Label 结构的原因是考虑到将来可能发生 rack 的扩容(假设新扩容的 rack 编号是 r6,r7,r8,r9,r10),这个扩容会导致 rack 数变多,当多个 TiKV 实例同时发生故障时,这些故障的 TiKV 出现在在多个 rack 上的概率也会增加,也就是会将第三章提到的 Multi-Raft 集群的可用性随节点数增加而下降问题再次引入到集群中。而通过使用逻辑层级 zone 保持与副本数一致可以将多个故障的 TiKV 出现在不同的隔离区(本例中的 zone)的概率降至最低,将来扩容 rack 也可以充分的利用到更多的 rack 的物理隔离来提高可用性。

在使用了 Label 隔离的集群中,存在以下限制:

规划了 Label 的集群再扩容时需要对每个隔离区进行容量一致的扩容,在本章的案例中,隔离区为 dc 和 rack 标示的位置,因此需要对每种 dc+rack 组合的区域进行容量一致的扩容,比如将要扩容 5 台 TiKV 服务器,其分配方法如下:

zone1=>dc1:rack1 增加一台 TiKV

zone2=>dc1:rack2 增加一台 TiKV

zone3=>dc2:rack1 增加一台 TiKV

zone4=>dc2:rack2 增加一台 TiKV

zone5=>dc3:rack1 增加一台 TiKV**

1、测试环境推荐配置

2、生产环境推荐配置

3、 如果 tikv 服务器的 CPU及磁盘配置较高,可以考虑多实例部署,按照每个 tikv 实例16~20core + 64G 内存 + 800G 磁盘的比例分配硬件资源。

同时需要注意 inventory.ini 及 ansible/conf/tikv.yml 的相关配置。

4、tidb 服务器视业务类型,如果业务逻辑有偏 AP 类的 SQL,需要考虑配置大内存,防止出现 OOM。

如果是纯 TP 类业务,tidb 服务器 CPU 配置较高的话,也可以考虑多实例部署,每个 tidb-server 分配20~32core,可以避免无谓的CPU上下文切换, 减少 system cpu 消耗。

5、pd 服务器的磁盘可以配置200~500G 的SSD 盘,主要用来保存源数据信息。在集群规模较大,源数据信息较多的时候,SSD 磁盘能够避免源数据信息存取成为集群的瓶颈点。

1、操作系统版本要求

建议 centos 7.3及以上,支持 redhat 7.3版本及以上,不推荐其他版本的系统。

2、ansible、jinja 等软件依赖包版本,只需要验证中控机(运行ansible 机器)上软件版本满足条件即可

中控机:

监控机(grafana):

3、测试环境磁盘 IO 不满足需求

ansible-playbook bootstrap.yml --extra-vars "dev_mode=True"

加上 dev_mode=True 可以在部署时,绕过系统磁盘相关的 benchmark

4、关闭防火墙、开启时钟同步

systemctl status firewalld

systemctl status chronyd/ntpd

5、集群下所有服务器要配置不同的 hostname

如果否,可以编辑 inventory.ini 的配置项 set_hostname=True 来自动修改 hostname

6、调整参数

参数在 ansible/conf/目录下,tidb.yml,tikv.yml,常见的可能需要调整的参数

tidb.yml:

grpc-connection-count: 如果服务器 CPU 配置较高,tikv 实例个数较多,该参数可以调整至20~32之间

slow-threshold:slow-query 记录的阈值,默认300ms

level:日志级别,默认 info,可以视情况调整为 debug 或 error

tikv.yml:

sync-log:raft-log sync配置,默认值true,对于磁盘 io 消耗较高,测试/非金融生产环境建议设置为 false

region-split-check-diff:检测 region 分裂的阈值,非 SSD 磁盘建议调大至32MB

rocksdb defaultcf block-cache-size(GB) = MEM * 80% / TiKV 实例数量 * 30%(多实例部署下配置,单实例部署不需要修改)

rocksdb writecf block-cache-size(GB) = MEM * 80% / TiKV 实例数量 * 45%(多实例部署下配置,单实例部署不需要修改)

rocksdb lockcf block-cache-size(GB) = MEM * 80% / TiKV 实例数量 * 2.5% (最小 128 MB)(多实例部署下配置,单实例部署不需要修改)

raftdb defaultcf block-cache-size(GB) = MEM * 80% / TiKV 实例数量 * 2.5% (最小 128 MB)(多实例部署下配置,单实例部署不需要修改)

多实例情况下,需要修改 

readpool:

  coprocessor:

  high-concurrency

  normal-concurrency

  low-concurrency

三个参数,推荐为实例数*参数值 = CPU 核数 * 0.8。

 raftstore:

   capacity

 磁盘总容量 / TiKV 实例数量,例如 “100GB”

修改完后,可以使用下面命令验证

cat tidb-ansible/conf/tikv.yml |grep -Ev "^$|#"

无误后执行 

ansible-playbook rolling_update.yml --tags=tidb/tikv

滚动升级,tags 可选

7、官网有比较完善的在线+离线部署方案、在线升级指导、在线扩容缩容文档,具体参考:

https://pingcap.com/docs-cn/op-guide/ansible-deployment/

https://pingcap.com/docs-cn/op-guide/offline-ansible-deployment/

https://pingcap.com/docs-cn/op-guide/ansible-deployment-scale/

1、从 MySQL 迁移

TiDB 兼容 MySQL 语法,小数据量建议直接使用 mysqldump、mydumper 来全量导出数据,再通过 source、myloader 的方式导入 TiDB。

./bin/mydumper -h 127.0.0.1 -P 3306 -u root -t 16 -F 64 -B test -T t1,t2 --skip-tz-utc -o ./var/test

./bin/loader -h 127.0.0.1 -u root -P 4000 -t 32 -d ./var/test

详情请参考: https://pingcap.com/docs-cn/op-guide/migration/#使用-mydumper-loader-全量导入数据

如果数据量较大,超过几百 G,可以联系原厂申请试用 lightning 工具,loader 导入数据平均速度是20G/小时,lightning 约为100~150G/小时

2、从 Oracle 迁移

目前有几种方式可以参考

使用 OGG 做全量+增量同步

使用 Navicat Premium 版的 data transfer 功能,支持从 Oracle/SqlServer 迁移全量数据至 TiDB

通过 kafka 等消息队列工具,解析 OGG 的日志,开发写入 TiDB/MySQL 的工具

目前我们也在积极跟专业的数据异构平台合作,争取能够尽快在更多的数据迁移工具中兼容 TiDB 数据源。

1、启动集群

ansible-playbook start.yml --tags=tidb/tikv/pd

在正确的 ansible 目录下,确保 inventory.ini 里的配置正确,tags 可选

2、停止集群

ansible-playbook stop.yml --tags=tidb/tikv/pd

在正确的 ansible 目录下,确保 inventory.ini 里的配置正确,tags 可选

3、停止单个 tidb-server / tikv-server

ansible-playbook stop.yml --tags=tidb/tikv/pd -l IP

-l 后面接 inventory.ini 配置的IP 或别名

4、访问 tidb

TiDB 兼容 MySQL 协议,所有连接 MySQL 的方式都适用于TiDB

mysql -uroot -h127.0.0.1 -P4000 -p

常见的图形化界面工具,navicat 等都可以直接访问 tidb

同时也支持jdbc、odbc 等,需要注意的是 mysql 8.0版本的客户端,及 mariadb 客户端可能存在兼容性问题,不建议使用

SQL 语法基本兼容 MySQL,某些不兼容的场景见: https://pingcap.com/docs-cn/sql/mysql-compatibility/#与-mysql-兼容性对比

5、修改参数

可以通过修改 tidb-ansible/conf/tidb.yml 配置文件,然后执行

ansible-playbook rolling_update.yml --tags=tidb/tikv

也可以直接登录服务器,找到deploy_dir/conf/tidb.toml,直接编辑文件,然后 pkill tidb-server 来重启服务

6、查看 tidb 版本信息

select tidb_version()

Release Version: v2.1.0-rc.3-24-g23f90a6

Git Commit Hash: 23f90a68be321e724280da6033a2b63ebf6cc7dd

Git Branch: HEAD

UTC Build Time: 2018-10-10 09:18:39

GoVersion: go version go1.11 linux/amd64

Race Enabled: false

TiKV Min Version: 2.1.0-alpha.1-ff3dd160846b7d1aed9079c389fc188f7f5ea13e

Check Table Before Drop: false

7、备份 tidb 数据

全量备份可以采用 mydumper,增量备份需要开启 binlog,实时恢复采用商业版工具 reparo。

8、查看监控数据

在 ansible 的配置文件 inventory.ini 里,有一个监控服务器的配置

[monitoring_servers]

10.1.163.87

deploy 的时候会默认在这个配置服务器上部署 grafana 组件,通过

http://10.1.163.87:3000 admin/admin  访问

具体一些常见的监控指标,请参考: https://pingcap.com/docs-cn/op-guide/dashboard-overview-info/

9、收集统计信息

set @@tidb_build_stats_concurrency=20

set @@tidb_distsql_scan_concurrency=100

set @@tidb_index_serial_scan_concurrency=20

analyze table xxx index xxx

修改上面三个参数可以提升 scan 效率。

具体统计信息相关,请参考: https://pingcap.com/docs-cn/sql/statistics/#统计信息简介

1、Transaction too large

TiDB 对于事务有限制,简单来说以下几点:

单个事务的SQL 语句数量不能超过5000,( 在 tidb.yml 可配 stmt-count-limit )

单条 KV entry 不超过 6MB

KV entry 的总条数不超过 30w

KV entry 的总大小不超过 100MB

备注:假设某张表有4个索引,那么一条数据对应的 kv entry 为数据+索引,一共5个kv 记录。

如果是批量 insert 或delete,建议先修改

set tidb_batch_insert = 1 

set tidb_batch_delete = 1

update mysql.tidb set variable_value='24h' where variable_name='tikv_gc_life_time'

再执行 SQL。

如果是批量 update,建议采用 limit 循环的方式执行。

2、GC life time is shorter than transaction duration

GC Life Time 间隔时间过短,长事务本应读到的数据可能被清理了,可使用如下命令增加 GC Life Time :

update mysql.tidb set variable_value='30m' where variable_name='tikv_gc_life_time'

3、Lost connection to MySQL server during query

log 中是否有 panic

dmesg 中是否有 oom,命令: dmesg -T | grep -i oom

长时间没有访问,也会收到这个报错,一般是 tcp 超时导致的,tcp 长时间不用, 会被操作系统 kill。


欢迎分享,转载请注明来源:夏雨云

原文地址:https://www.xiayuyun.com/zonghe/488674.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-06-13
下一篇2023-06-13

发表评论

登录后才能评论

评论列表(0条)

    保存