写点什么

TIDB 调优小结

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

    阅读完需:约 19 分钟

作者: eshin_ye 原文来源:https://tidb.net/blog/f746840d


https://blog.csdn.net/qq_22351805/article/details/113566849


本人博客原地址:TiDB 调优小结


创作时间: 2020.12.25 19:03:42


TiDB 概览

先来一段官网的描述

TiDB server: 无状态 SQL 解析层,支持二级索引,在线 ddl, 兼容 MySQL 协议,数据转储

SQL 输入 -> 解析语法树(AST)-> 逻辑计划分析 -> 执行计划优化

->cost-base model-> 物理计划选择 -> 计算下推 tikv-> 聚合 tikv 执行结果

PD server: 协调层,存储集群元数据,region 调度,事务时间戳 TSO。存储每个 TiKV 节点实时的数据分布情况和集群的整体拓扑结构,内置仪表盘 dashboard.

TiKV/TiFlash: 存储层,tikv 行存储引擎,事务类处理走 tikv;tiFlash 列存储引擎,分析类处理走 tiFlash。tikv,基于 LSM 算法的 RocksDB 单机 Key-Value 存储引擎,TiDB 的 SQL 层做完 SQL 解析后,会将 SQL 的执行计划转换为对 TiKV API 的实际调用。

tikv 存储单位为 region,关于 region 的介绍可以参考这里同时里面还有 raft 的相关介绍,目前最主要记住 TIKV 以 Region 为单位做 Raft 的复制和成员管理同时只需要同步复制到多数节点,即可安全地认为数据写入成功


特性:

易拓展:计算能力 (TiDB) 和存储能力 (TiKV) 均可水平拓展,但集群中只有一个 PD 能被选举为 leader

高可用:TiDB/TiKV/PD 三大组件均可 cluster 模式部署

高效存储:基于 LSM 算法的 RocksDB 单机存储引擎,lz4、zstd 等高效压缩算法, 除了 RocksDB 之外,TiDB 还支持一些流行的单机存储引擎,比如 GolevelDB、BoltDB 等

安全存储:采用 Raft 协议复制数据,多副本防止单机失效

分布式事务:支持 ACID 事务,不同于 XA, 客户端调用无需设置数据源为 xa,天然分布式事务

易用性:支持 MySQL 协议,使用 MySQL 语法,MySQL 客户端均可直接连接登陆


因测试环境受限,我们的环境较多软硬件都不符合官方配置要求,啊哈哈哈。。。但这并不影响我们对技术的研究和使用,再穷也要创造条件顶硬上。


## 一、部署环境



其余硬件,实际部署环境 CPU 8 核,内存 16G,千兆网卡。


官网推荐如下




TiDB 和 PD 可以部署在同一台服务器上。

如对性能和可靠性有更高的要求,应尽可能分开部署。

官网参考

虽然实际测试环境,使用的 raid 挂载的是机械硬盘,但是读写能力并不弱,dd 指令数据如下:


本次使用主机 11 台(10.248.7.154-164)

二、拓扑


查看集群状态

tiup cluster display tidb-test

当然还有更直观的仪表盘(PD 内置,访问 PD 服务 http:ip+port/dashboard). 也可以先在部署 TiUP 的机器执行 tiup cluster display tidb-test –dashboard 得到,即

使用数据库用户 root 登陆

还可以使用额外部署的 grafana:http://10.248.7.163:3000

三、测试与优化

场景:大文件, 多文件数据入库,入库首先保证速度,最终一致即可(CAP 中的 AP)文件有备份,可重新入库。入库后简单 OLAP 操作。

测试准备:入库应用(可配置单次入库记录数),500 万行数据文件(写成 6 个文件)

这里先来说一个异常场景,这个场景刚好可以对比磁盘性能差异引起的 tidb 性能差异,同时对理解热点问题和对应调优有一定帮助。

在最开始压测的时候,tikv 节点的三台主机(raid 22 块磁盘),其中有两台主机 raid cache 电池故障,导致 raid cache 失效,这两台主机的 IO 性能严重受影响

当然,在测试的时候,事先是并不知道这个问题的,并在此基础上做了一些研究和调优。接下来简要说下过程(以下过程均访问单个 TiDB-server):

1、首次压测(单批次 5000 行记录,5 线程)

由于扩展 tikv 前的图已丢失(现 raid 电池问题已修复,无法重现),只能贴上 4tikv 的图了,不过除了加多一个节点,现象差不多,后面再做扩缩容的演示

由图可以看出,除了正常的 161 外,其余的 tikv 节点,IO 均已跑满(163 为应用部署主机)。考虑两点,磁盘性能差异、region 分布不均匀。

再来看下热点 region 的图:

可以看出,hot region leader 的分布非常不均匀。以三副本(peer)为例,根据 raft 协议,当写入时,首先写入到 region leader,写完 leader 之后再同步拷贝到其余两个节点的 region follower 参考官网说明。这里就考虑两个热点部分不均匀的可能:1、单批次提交事务过大,导致同一时间内数据集中在一个 region,在未超过一定大小时(默认 96M)并没有分裂 region;2、主键有序程度高,导致排序分裂 region 时,数据在 region 中比较集中。

入库结果:

平均一百万行需要 6-7 分钟。从文件数据看,先慢后快,这跟初始化时只有单个 region 有关,只有达到单个 region 限制后才会分裂。参考这里可先不对此过度优化。

2、第二次压测(单批次 2000 行记录,10 线程)

基于第一次的压测结果,修改单批次提交记录数,并加大线程分散提交的事务。修改后 tikv 节点的 IO 使用率并无太多变化。入库速度略有上升:

3、第三次压测(单批次 2000 行记录,10 线程,乱序)

在修改了批次大小后,继续修改使主键乱序,同上,IO 使用率依旧没有多大变化。不过入库速度有较大提升(平均一百万 3 分钟):


经此两次调整后,region leader 热点已分布比较均匀:



到目前为止,一直忽略了一个事情,没有观察总的 region leader 情况:

从图看,总的 leader 分布是很均匀的, 且写入字节总量各个 tikv 节点也大致相同,但是 hot leader 为什么这么不均匀而且为什么其中一个 tikv IO 使用率低这么多呢,矛头指向了磁盘性能问题,经排查后发现,磁盘电池故障,raid cache 失效。

4、第四次压测(单批次 2000 行记录,10 线程,乱序,sync-log = false)

在磁盘问题修复前,我们找到一处关于sync-log 的说明


以三副本为例,需要至少写完两个副本之后,才能向客户端返回 ack。因此关闭同步日志,异步写 follower 的副本,相当于写单机的时间。这里牺牲了 CAP 中的 C,只需最终一致即可。我们的应用场景适用,同时我们文件有备份,即便出错可以重新导入。但是对于实时性较强,对一致性要求较高的金融场景,不建议关闭同步日志。

操作需使用 Tiup:

执行 tiup cluster edit-config tidb-test

修改完成后执行:tiup cluster reload tidb-test -R tikv 重启 tikv

修改后入库效率如下:

一百万行记录入库时间优化到 2 分钟。


不过在修复磁盘后发现,这个参数在我们的场景影响并不是很大,良好的 io 性能使得这个参数设置变得不那么重要,因此在修复磁盘后的测试中,我们都是基于开启同步日志的场景


修复磁盘后测试

修复后的 tikv 磁盘性能均有如下表现:


修复磁盘后,我们测试的条件为:3TiKV3 副本,单批次 2000 行记录,10 线程,乱序。恢复同步日志配置的修改。

来看下修复后的 TiDB 表现:

hot region leader 均匀分布,peer(副本)也是均匀分布

入库效率如下(平均 100 万行记录 1.5 分钟):

直觉告诉我们,事情肯定还没有结束,应该还有优化的空间。似乎到目前为止,我们都没有好好看看 TiDB-server 的情况:

到目前为止,我们都是直接访问单个的 TiDB-server。因此出现了如图的 CPU 负载情况,只有 157 的 tidb CPU 快到 7 个核的使用率。由于 tidb-server 是无状态的,可以通过负载来给另外两个 tidb-server 分活了。本例使用 NGINX,配置如下:

修改访问地址,客户端通过连接 NGINX 访问 tidb 10.248.7.154:4000


通过 NGINX 负载后,每个 tidb-server 的 cpu 都得到了利用,同时平均一百万行记录入库时间优化到 1 分钟。

按照对官方文档的理解,tidb 的计算能力和存储能力都可以扩展,目前我们通过 NGINX 负载实现了 tidb-server 计算能力的负载。但是计算不仅仅在 tidb-server。tidb-server 解析 SQL 生成执行计划之后,会有一部分的计算下推到 tikv。这也是为何 tikv 和 tidb 这两个组件的实例不能部署在同一台主机。那么扩充 tikv 节点后,性能会有多大程度提高?另外扩充的节点会不会自动协调原有节点的 region 呢?

扩展 tikv 节点

扩展前,肯定要先看看原有的磁盘占用情况:

扩容过程中,正逐渐转移数据到新的 tikv 节点。稳定后如下图:

不过在入库效率上,提升并不明显,时间上和扩容前相差不多。有以下原因,原本的三节点并行入库性能还有较多可利用空间,相当于只是把部分处理迁移到新节点,单原先节点的处理能力还有很多富余,需要原先的节点 IO 和 CPU 有较高使用率时,扩充节点才能有较多的性能提升region 调度策略

CPU 和 IO 使用率都不大。

同等主机环境的 MySQL 入库情况如下:

在主键无序的情况下,随着数据量的增大,入库性能急剧下滑,这跟索引树叶子节点在主键无序时,频繁分裂调整树结构有关。主键有序时,入库性能中 规中矩,不过即便是有序,在数据量多了以后,入库性能也会下滑。所以 MySQL 单表有大小要求,超过一定大小之后最好选择分库分表,但是这也会引入另外的问题,业务应用测也要对此做大量的改造。

同等主机环境 MySQL 与 tidb 查询性能对比:

当前分区 500 万行记录查询, 查询 SQL


select SETTLE_DATE AS "账期日",COUNT(0) AS 成功条数,SUM(JSON_EXTRACT(JSON,'$.Payment')) AS 成功总金额(分)  FROM BL_BATCH_TEST TDPWHERE TDP.SETTLE_DATE = '20201201' and JSON_EXTRACT(JSON,'$.IsSuccess') = '0' and JSON_EXTRACT(JSON,'$.Result') = '0' group by SETTLE_DATE; 
复制代码



TIDB


mysql

(mysql 的数据同事帮我跑的,啊哈哈)

对比来看,tidb 查询性能较为稳定,即便重启所有组件清楚缓存后(图中第二次查询 ),单个分区 500 万行记录,查询 8s, 再次查询时间减半,MySQL 第一次查询耗时 80+s, 第二次查询也能维持较好的性能。通常业务查询(OLAP),最重要的是首次时间,第二次的查询时间参考意义不大,因此稳定的查询时间尤为重要。MySQL 和 tidb 在重启后,首次查询时间都相对要久一点,这跟加载磁盘数据到内存耗费有关,tikv 几个节点堆起来的内存跟 MySQL 单机的内存比,是不太公平的,但这也正是 tidb 的优势。

总结:

1、TiDB-server 是计算密集型组件,同时也会将部分计算下推到 TiKV,而 TiKV 是 IO 密集型组件,因此 TiDB 和 TiKV 不能在同一台主机部署。PD 存储元数据会频繁写磁盘,对磁盘 IO 要求高,因此也不能和 TiKV 同部署,PD 可以和 TiDB-server 同主机部署。

2、TiKV (集成 raft 协议)以 region 为存储单位,超过默认 96M 后会分裂,通过 raft 协议做 leader 选举和副本(即 peer)复制,每个 region 都会有 leader 副本,其余的副本为 follower,客户端读写只会通过 region 的 leader 节点,写入时,写完 leader 后再复制到 follower,超半数以上副本写入完成即认为写入成功。

增减 tikv 节点,或者修改 replication.max-replicas 后,PD 会通过 region 的心跳判断当前副本情况,从而调度副本到新节点或者增减副本。

3、通过 grafana 和 PD 自带的 dashBoard 可以实时查看当前系统的问题,比如 TIDB 节点的 CPU 使用率、QPS;TIKV 节点的 CPU、IO 使用率 ; 通过 PD 查看热点分布和 region 分布于调度情况 ; 通过 PD 的 dashBoard 查看慢 sql, 集群状态,调用栈火焰图等等。

CPU 使用率单核不要超过 80%,超过不管是 TIDB 节点和 TIKV 都要考虑扩容

tikv 节点内存不要超过 60% 使用率,IO 达到 80% 可视为到达瓶颈

4、region 数量单个 tikv 小于 50K, grpc 延迟尽可能小于 100ms。过多的 region 会导致调度频繁影响性能,grpc 延迟增大。可考虑设置 region 合并参数


以下配置意为:key数目小于200000,region大小小于20M的合并(默认)set config pd `schedule.max-merge-region-keys`=200000;set config pd `schedule.max-merge-region-size`=20;
复制代码


5、当 TIDB 节点 CPU 过高时,如是正常 SQL 执行需要,可考虑增加 TIDB 节点,并通过 Nginx,HaProxy 等负载工具分发到不同节点执行。当 Tikv 出现较高水平的 cpu 使用率或者 IO 使用率,可考虑增加 TiKV 节点。TiKV 对磁盘要求较高,尽量使用SSD 磁盘,或者多磁盘 raid

6、出现热点 region 的时候,有几个地方可以查看,比如 grafana 监控中的 PD 可以看相关的 hot region 分布情况,这是最直观的方式;还可以通过监控中的 tikv,查看各节点 CPU 和 IO 使用情况,当出现热点问题是,这两个指标在各个节点时很不均匀的,尤其 THread cpu 的 corprocessor 或 scheduler(负责读 / 写模块的线程)。

7、解决热点 region 的问题,主要在于分散 region 数据的分布,减少频繁读写同一个 region。通过减少单批次提交记录数(小事务),非自增乱序的主键(官网要求 int 类型的主键。5.0 之后将支持 vchar),频繁访问相同数据通过内存访问,从业务层面拆分热点数据等手段减少热点。但在所有的 tikv 都出现较多热点 region 时,这时应考虑扩充 tikv 节点。当 tikv 节点 region 分布不均匀,CPU 和 IO 使用率不均匀时,还应考虑硬件性能问题,部分硬件性能会影响整体系统性能。

8、RocksDB 默认使用 snappy 压缩算法,不过 TiKV 有分层使用压缩算法,默认[“no”, “no”, “lz4”, “lz4”, “lz4”, “zstd”, “zstd”]当数据量超过 500G 时 RocksDB 的层数才会超过 4, 超过 500G 部分的数据才会启动 ZSTD 压缩算法。lz4 解压缩速度及压缩比都优于 snappy;ZSTD 压缩比更高,解压缩比 lz4 慢,适合层级高的老数据。

9、RocksDB 的 LSM 树

如图:wal 相当于 MySQL 的 redo log。从 wal->menorytable(可修改 Memtable–》不可修改 immutable Memtable)->SST,读放大和写放大问题都会存在,写放大在于 sst 逐渐往下 compact(异步线程);而读放大在于需要逐层查找,且层数越往下,压缩率越高,效率越低。

10、理论上,tidb-server 节点和 tikv 节点都可以无限扩充,但是 PD 整个集群只能有一个 leader,因此扩充能力受限于 PD 节点的处理能力,此外网络带宽也是限制因素之一。

未完待续…

raft 算法与分布式事务 percolator、两阶段提交

raft 算法笔记

为何使用 kv 存储引擎

两个 tidb 集群间实时同步(异地双中心双活)

参考资料

TiDB 官网


官网 FAQ


TiDB in action


在线修改配置,非持久化配置


LSM && RocksDB compaction 策略


RocksDB 解析


region 调度策略


TiDB 高并发写入场景最佳实践


TiDB 热点问题处理


海量 Region 集群调优


Percolator 和 TiDB 事务算法


TiDB 集群推荐使用 SSD 的原因


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

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

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

评论

发布
暂无评论
TIDB调优小结_TiDB 社区干货传送门_InfoQ写作社区