Java教程

理想汽车 HTAP 读流量优化指南

本文主要是介绍理想汽车 HTAP 读流量优化指南,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
“没有任何一种数据库是银弹,业务场景的适配和降本增效永远是最重要的。” 数据库的性能优化能够帮助企业最大限度地利用系统资源,提高业务支撑能力和用户体验。本文为 TiDB 性能调优专题的第一篇,在这个专题中,我们将邀请更多 TiDBer 从实际的业务场景出发,分享 TiDB 优化的最佳实践。


作者介绍

郑赫扬(艺名:潜龙),理想汽车 DBA。负责公司分布式数据库的技术探索和业务场景落地,热爱开源。就职于金融、互联网教育、电商、新能源汽车等领域。

理想汽车作为豪华智能电动车品牌,以 “创造移动的家,创造幸福的家” 为使命。随着电动汽车业务的不断发展,公司业务既有 OLTP 也有 OLAP 的需求,因此需要一款 HTAP 数据库帮助公司实现实时业务决策。在 TUG 企业行 —— 走进 58 同城活动中,来自理想汽车的郑赫扬老师为大家介绍了理想汽车 HTAP 读流量在物理环境、业务环境、SQL 优化、热点问题、流量环境、版本及架构等方面的优化方案。


以下为演讲实录。

理想汽车选择 TiDB 的理由

1)一栈式 HTAP:简化企业技术栈

TiDB 可以在一份数据源上同时支撑理想汽车 OLTP 和 OLAP 需求,不但能很好地支持实时数据落地存储,也能提供一体化的分析能力。另外,TiDB 也可以集成常见的大数据计算技术框架,比如 Spark、Flink 等等,可以使用其构建离线或者实时的数据仓库体系。

2)解决 MySQL 传统拆库拆表问题

随着数据量的激增,单机数据库存不下怎么办?传统关系型数据库再扩展性问题,如果业务上已经用了 MySQL,那只能去做分库分表,或者利用中间件去转化,业务层要把代码改个遍。而 TiDB 与 MySQL 完全兼容,MySQL 应用无需修改便可直接运行。支持包括传统 RDBMS 和 NoSQL 的特性,可以随着数据增长而无缝水平扩展,只需要通过增加更多的机器来满足业务增长需求。

3)简约但不简单的扩缩容

在经历产品更新的演进中,TiDB 4.0 和 5.0 版本基本上可以通过一些操作控制来灵活便捷地扩缩容,例如通过增加节点来线性扩展计算能力,存储节点同样可以根据存储需求不断进行扩容增加存储。在进行节点缩容时,对线上服务的影响也几乎无感知。

4)完善的生态工具

目前理想汽车正在使用 DM(TiDB Data Migration)、TiCDC、TiSpark 等工具,在实际操作中也很强烈的感受到 TiDB 生态工具非常全面,这些生态工具还在不停地演进发展中,我们也在和官方小伙伴一起探索。

5)丰富的场景支持

TiDB 在理想汽车的业务场景包括 OLAP 和 OLTP 两个维度。OLAP 包括离线数仓,实时数仓、DMP 平台(包括日常的决策调度、财务调度、报表等);OLTP 类的商业前端、算法训练(包括线上派单、交付、信息上报)等等。

6)良好的社区环境

社区一直是培养 TiDB 不断发展的优渥土壤,在日常维护中一旦出现故障和难点,官方的技术人员就会马上处理,这也给理想汽车很大的信心把 TiDB 引入更多业务场景中使用。


接下来跟大家介绍理想汽车针对读流量在以下 7 个方面的优化实践。

HTAP 读流量如何优化?

1)物理环境优化

https://img2.sycdn.imooc.com/6184b0450001d39f10800302.jpg理想汽车目前把 TiDB 和 PD 集群的配置从原来的 16 核 32G 升级成了 32 核 128G。对于 TiDB 来说,支持 AP 类的大 SQL 可能要跑 7 - 8G 左右的内存,对内存的需求更高。为了解决 PD 的算力问题,我们会预估一下数仓的数据级,预估之后我们会再调大,例如一个单点的话,一个 PD 在 50 万以上可能有调度问题。所以我们可以调大 Region,来横向避免 Region 数量过多的情况。TiKV 刚开始使用的是 32C32G 2T 的百度云 SSD,现在和 TiFlash 一样全部采用 32 核 64G 的 4T NVMe 物理盘,这两个升级都是为了更好地统筹计算资源。


2)业务环境优化

目前在理想汽车主要的 TiDB 集群都由 DM 同步上游的 MySQL,针对 DM 集群管理做了大量优化。做完之后,就是现在所有的上游 MySQL 主要库在 TiDB 里面都会有副本,因此 TiDB 就具备了 MySQL 从库 + 业务主库 + DMP 平台结果库的功能。https://img1.sycdn.imooc.com/6184b0460001798510800469.jpg

关键业务库表 DDL 变更和业务变更

  • 上游 MySQL DDL 变更是否允许都会做一个规范,防止同步任务中断。
  • 新业务完整的测试环境支持。
  • 上游 MySQL 刷业务数据会有大量写流量,DM-sync 线程扩容。刷数据之前大家需要提前自动化,调整到高峰以应对流量冲击,因为下游有很多重要的业务,数据延迟的话会很有影响。

分类开发规范:

  • OLTP 开发规范:目前理想汽车的单个事务 SQL 结果集大小不能超过 20MB 结果集 50W 以下,或者 TiDB 计算节点内存小于 120MB,因为 TiDB 要对结果集做一个处理,可能最大扩大至 6 倍。


  • OLAP 开发规范:

  1. 复杂 SQL 大表走 TiFlash (一般 2KW),小表走 TiKV。

  2. 结果集最大值小于 7KW 或者 TiDB 计算结果内存小于 8G。

  3. 不断探索 TiDB 的 OLAP 性能边界。


DM 优化:

DDL 的问题是不支持变更,假如下游读流量业务受到影响,例如公司上游挂了很多个 MySQL,你希望做 MySQL 同步关联,你只要同步在一个 TiDB 集群里面,你也可以做一个小的数仓,调整方法,首先调整 TiDB 支持 DDL 变更。


解决方法:(1)调整 TiDB 支持 DDL 变更(2)上游新建表 --> 插入业务数据 --> rename 表名 --> 跳过报错(针对上游流量和数据量小,要做数据修补)(3)下游新建表 --> 插入业务数据 --> rename 表名 --> 跳过报错(下游不会丢失数据)


业务环境优化中,典型的 TP 类型的 SQL 对结果集和算子要求就是 20MB,比如需要考虑环境规划,我们要求结果集在多少,总共不能少过多少万行或者多少的内存,下图所示最大内存是 25.3MB。https://img2.sycdn.imooc.com/6184b04600019a8a10800615.jpg再来看下 AP 类型的 SQL 实时数仓,最大内存是 8G,总共少了 7700 万的数据,执行时间是381 秒,是用 TiFlash 跑的。因为有的报表类或者是定时任务实时性不高,所以分类的话,还是 OK 的。我们现在好多类似的 SQL 在这么跑,TiFlash 5.0.2 集群版本,对于我们来说还可以,业务上比较稳定。https://img2.sycdn.imooc.com/6184b0470001708b10800327.jpg


3)SQL优化

首先得定一下规则

SQL 索引:

  • OLTP 类:决定查询速度,所有 SQL 必须走索引
       a. 注意不走索引的情况(where 条件中左侧等式函数,隐式转化,不等式)        b. 优化方式 MySQL 索引基本一致
  • OLAP 类:根据表的数量级和 SQL 复杂度
        a. 行存 where 条件查一条数据,行存 + 索引更快。        b. 列存没有细粒度索引,扫描数据性能更好。DDL 大表(数量过 10 亿)索引上线可能会影响线上业务:1. 参数调整:业务高峰调小调低优先级
  • tidb_ddl_reorg_batch_size = 128

  • tidb_ddl_reorg_worker_cnt = 2

  • tidb_ddl_reorg_priority = PRIORITY_LOW


2. 业务低峰调大调高优先级(看监控观察业务)
  • tidb_ddl_reorg_batch_size = 1024

  • tidb_ddl_reorg_worker_cnt = 16

  • tidb_ddl_reorg_priority = PRIORITY_HIGH


SQL 执行计划:

读表算子 TiDB 和 MySQL 不一样。MySQL 的话是 Type、Reader 之类的,但是 TiDB 是有分成算子再往下去读像 TableReader,点查大于索引覆盖,相当于 MySQL 的索引覆盖,相当于 TiDB 普通索引。读表算子优劣:PointGet/BatchPointGet>IndexReader(MySQL覆盖索引)> IndexLookupReader(普通索引)> TableReader。对于 TP 类型 SQL 来说尽可能消除 TableReader 读表算子或者减少结果集。https://img2.sycdn.imooc.com/6184b0470001313210800366.jpg

SQL 错误索引与统计信息:

TiDB 统计信息和表格健康度会直接影响你的索引,通常就不走了,所以你的业务突然就变慢了,只能说越来越小了。对于理想汽车来说,看表的健康度只要是大于 80% 的话,正确索引的概率基本上是可以保证的。


解决方法:手动或者自动更新表和索引统计信息(1)自动更新条件
  • 表中至少 1000 行数据

  • 默认 1 分钟无 DML

  • modify_count > tidb_auto_analyze_ratio参数(默认 0.5,设置成 0.8)

  • tidb_build_stats_concurrency(默认 4,资源充足可以调大)

  • tidb_distsql_scan_concurrency(默认 15,AP 30,TP 10)

  • tidb_index_serial_scan_concurrency(默认 1,TP 不调,AP 调成 4)

https://img2.sycdn.imooc.com/6184b048000100a510800127.jpg解决方法:(1) 设置自动 analyze 时间 -tidb_auto_analyze_start_time(这里是 UTC 时间,如果是默认值00:00 + 0000,则早上 8 点开始执行)。所以建议设置时间为业务低峰 -8 小时,比如凌晨执行(16:00 + 0000),结束 tidb_auto_analyze_end_time 设置(23:59 + 0000)。(2) 如果仍然不准确,可以适当入侵绑定 SQL 计划或者强制走索引。
  • CREATE [GLOBAL | SESSION] BINDING FOR BindableStmt USING BindableStmt;

(3) 如果避开了自动 analyze 时间,则应该手动重新统计表信息。
  • show stats_meta where table_name='xxx'

  • show stats_healthy where table_name='xxx'

  • show STATS_HISTOGRAMS where table_name='xxx' analyze table xxx;

https://img2.sycdn.imooc.com/6184b0480001378210800428.jpg

SQL 逻辑优化

TiFlash 函数下推,大家一定要看一下,因为 TiFlash 不是所有的函数都下推。假如你走 TiFlash 数据量很大,又没有函数下推,代表你会在 TiDB 里面计算,这个过程可能就会比较耗时。建议对准官方的支持列表,(下图为部分截取)按照下推列表去规范 SQL。https://img1.sycdn.imooc.com/6184b04900015a0f10800360.jpg


4)热点问题优化

业务报慢 SQL,监控看单个节点 Coprocessor CPU(Coprocessor 是 TiKV 中读取 数据并计算的模块)异常飙升。(v3.0.14 未开启 Unified read pool,面板指标 TiKV - Details -> Thread CPU)https://img4.sycdn.imooc.com/6184b0490001720910800404.jpg- 看读热点,可以基于命令行去做一个脚本,比如 pt-ctl,看 hot read 和 hot write。(1) 去看 region 对应的表是哪张,获取热点的单个 region。(2) 4.0 以上 dashboard 热力图。(3) TiDB_HOT_REGIONS 表中记载了是那张表,有多少个字节。https://img1.sycdn.imooc.com/6184b0490001b89710800395.jpg然后手动 split Region,然后 hot read schedule 进行调度,CPU 使用资源下降,单个读热点 region 就消失了。

modb_20211105_825e7408-3dcc-11ec-a75d-38

V4 版本有一个参数 Load base Split,默认 10 秒内 3000 次查询,或者是流量超过了 30MB/秒自动分类。每一家的业务都不一样,每一家的集群也不一样,默认只是说是一个挺好的配置,但是大多数的部署 TiDB 可能用的不是 NVMe,可能用的是云盘的 SSD 或者是普通的 SSD,每一家的读流量标准应该根据各自的硬盘配置标准,设置一个正常流量均衡的 Region。这个可以通过热力图,也可以通过抓取的方式去看,可以做成自动化监控。所以 TiDB 还有个好处就是 Information Schema 里面几乎涵盖了你所有的信息,比 MySQL 更全。modb_20211105_826c1a5e-3dcc-11ec-a75d-38像监控、命令可以看最高的读取热点,每天都可以看,用命令行做一个筛选,找到对应的库表切割,切割完之后或者自动切割都可以,然后再观察。但是这个 Load base split 有的时候也有可能,也可以每天跑一遍检验它的结果。modb_20211105_827f0308-3dcc-11ec-a75d-38


5)流量环境优化

第一,强制 SQL 里面走一些执行计划,执行内容可以限定一个参数,比如说 10 秒,或者内存 20M。我们针对线上 TP 类型是有的,比如下图这个业务的 SQL,就是点击类的报表系统,因为点击类的报表系统由于业务人员选的维度不同,最后的数据量级也不同,你可以设置一个限制,否则可能他点很多次的话,一个大的流量就会把你的集群冲击掉。modb_20211105_828deb66-3dcc-11ec-a75d-38Optimizer Hints 熔断:
  • 执行时间: MAX_EXECUTION_TIME(N)

  • 执行内存: MEMORY_QUOTA(N)

  • 线上 TP SQL

第二,Global 参数配置确保资源不溢出和连接质量。
  • 长连接控制: pt-kill 控制杀掉 Sleep 线程或者重启 TiDB-Server(慎用)

  • 执行内存: tidb_mem_quota_query

modb_20211105_829da6c8-3dcc-11ec-a75d-38第三,理想汽车 AP 和 TP 读流量是分流的,TP 走的是 TiKV,AP 走的是 TiFlash,线上默认所有库表都加了 TiFlash 副本,有 3000 多个同步任务,大概是 3000 多张表,做一个流量分流。有的时候可能走 TiKV 更快,但是有的时候是一个整体切割,如下图所示,现在是两个流量分流了。modb_20211105_82b2d322-3dcc-11ec-a75d-38
  • AP 和 TP 的流量均摊,可以更改执行计划,但是我们用 Hint 更改执行计划,发现对 AP 类型非常不友好,测试的时候可能还会走到 TiKV 上面。SELECT *+ READ_FROM_STORAGE(TIFLASH[test1.t1,test2.t2]) */ t1.a FROM test1.t t1, test2.t t2 WHERE t1.a = t2.a;
  • Session 会话控制,需要配合 rollback 回滚参数使用,强行走 TiFlash。set @@session.tidb_isolation_read_engines = "tiflash";
  • TiFlash 下面有一个参数一定要设置,就是如果 TiFlash 发生查询错误,业务语句返回 TiKV 查询数据。确保万一 TiFlash 副本不能用了,还有读取数据的机会。set global tidb_allow_fallback_to_tikv='tiflash';

6)版本优化:

5.0 版本因为有 MPP 功能,我们去尝试从轻 AP 类型转到 AP 类型,看是否可以免除业务迁移的麻烦。我们的测试结果拿 2 台 TiFlash 做 MPP 测试作为参考,结果如下:
  • 2 台 TiFlash MPP 业务整体提升 35%。

  • 业务 SQL 比较复杂,5.0.2 之后官方做了更多的下推优化。


下图可以看出优化前后的运行时间对比。这些都是线上业务,线上的数仓 SQL 特别复杂,都是一两千行的大 SQL,打开文本看大概有 1400 行,所以这个优化效果还是很棒的。modb_20211105_82c9ddce-3dcc-11ec-a75d-38生产环境中,我们用 5 个 TiFlash node 跑,这是前后的流量对比图,整体有 32 秒,后来基本都降到了 1 秒以下。

modb_20211105_82dc6124-3dcc-11ec-a75d-38

但是这个图很骗人的,大家千万不能相信这个 999,你真正需要优化的,可能就不在这个 999 里面,全在那个 0.01 里面。但是整体优化的效果还是很明显的,包括事务延迟执行 lantency,都降低了很多。整体的响应更具说服力,以下是一天时间内的对比图,大于 30 秒的 SQL 少了 87%,大于 60 秒的 SQL 也降低了 87%,大于 2 分钟的 SQL 同比降低了 99%,同样的流量,5.0.2 对我们整体的优化提升还是非常大的。

modb_20211105_82ef5f7c-3dcc-11ec-a75d-38

7)架构优化

架构优化的核心思想是用技术架构来转化 SQL 压力,下图是实时数仓的技术架构。上面是 DM 同步 MySQL 的数据源写入到 TiDB,TiDB 做一个 ODS 层之后,再导入到 TiCDC,之后通过分区打入到 Kafka,再分批消费进入 Flink,然后数据回写回 TiDB,提供实时数据和物化视图功能。因为 TiDB 本身不支持物化视图,可以在 Flink 里面解决这个技术难题,打造一个流批一体的实时数仓。

modb_20211105_8303299e-3dcc-11ec-a75d-38考虑到 OLAP 业务 SQL,我们选择了 TiKV 存储引擎,这个时候在 Flink 做完计算的表再写回 TiDB 的话,有一些 AP 的 SQL 就可以变成 TP 了,像 Table Reader 的算子有的时候可以变成 PointGet 或者是 BatchPointGet(点查或者表查),范围查询就会少很多,这样就在侧面缓解了压力。选择 TiFlash 就可以完成各种维度的聚合操作,实现离线报表和在线统计这些功能。这些都是我们已经实施上线的,但是还有几个使用问题,例如:
  • 在理想汽车的 DM 场景下,对表做了 rename 后 TiCDC 就无法识别了。因为 TiCDC 默认是以 Table ID 算的,表名一样,但是里面的 Table ID 已经变了,TiCDC 识别不了,就只能重启;

  • 新增的 Kafka 分区,流量增大时增加 Kafka 分机,TiCDC 无法识别,也需要重启;
  • V4.0.14 版本以前的 TiCDC 稳定性存在问题。


总结

业务发展推动技术革新,目前理想汽车的发展非常快。TiDB 的读流量优化是个全局视角,除了 SQL 本身外,官方提供了非常全面的优化手段,包括引擎、架构、执行计划、参数控制等。大家可以去按照自己的业务发展去做各种不同的尝试。

当然,优化都不能只看表面,TiDB Duration SQL 999 线是最常看的指标,但是也有欺骗性,但有时候最需要优化的是那 0.01%。
最后,没有任何一种数据库是银弹,业务场景的适配和降本增效永远是最重要的。TiDB 更像是集百家之长,而不是专精于一技,在解决分库分表的基础上,基本覆盖所有场景和生态支持。理想汽车也希望能和 TiDB 一起走得更远。


这篇关于理想汽车 HTAP 读流量优化指南的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!