7 TiKV 节点写入性能在 2~5w rows/s,如何进一步优化?

  • 【TiDB 版本】:TiDB-v4.0.1
  • 【问题描述】:

我司搭建了 7 TiKV 节点的 TiDB 集群,TiKV 配置为 16C/32G/2TB PL 2 ESSD(阿里云标称 10w IOPS),这个集群有其它负载,折扣下来大约有 4 个 TiKV 节点轻负载吧,数据三副本,硬件约莫对应一台 16C/64G 内存的 MySQL。

我使用 TiSpark 写入 40~200w 行数据,多次试验,写入速度在 2w~5w rows/s,表格 schema 如下。

我做了个宽表试验,下表是每天一行,我把列扩充成 fof_nav_1, fof_nav_2, … fof_nav_31 这样的,一共 4 + 8 * 31 列,这样把一个账户一个月的数据存到一行上,将近 40w 行(只取了同一个月的数据,所有用户的子集),测试多次后,写入速度在 1.5w~2w rows/s。

我的 spark job 配置:driver 1 x 4C/8G, executors 8 x 8C/32G
spark.tispark.writeThreadPerTask=10
spark.tispark.regionSplitNum=32
bytesPerRegion=10485760 (10 MB)

使用类似的表结构 (id BIGINT primary key, cal_date, txn_account_id, account3_id, broker, fof_nav, fof_input_share, …),有三个二级索引,id 是个自增序列,但是由于 spark 并发写入,也会导致一定程度的乱序。以 8 x 4C/32G spark executors 测试写入 16C/64G MySQL,可以达到 30w rows/s。

我试验了 TiSpark 里用 jdbc 方式通过 tidb server 写入 tikv,比直接写 tikv 略慢。

所以目前的状态是,对等硬件条件下,TiKV 的写入性能在 MySQL 的 1/6 ~ 1/10,这挺悲剧的,我希望目前的 TiKV 集群规模能到 MySQL 1/3 写入性能,也就是 10w rows/s,目前离这个目标还挺远,不知道在目前 TiDB 4
集群里,还有没有进一步优化的可能,以及朝什么方向去优化?

表格 schema 如下:

MySQL [test]> show create table t\G
*************************** 1. row ***************************
       Table: t
Create Table: CREATE TABLE `t` (
  `account3_id` bigint(20) NOT NULL,
  `txn_account_id` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL,
  `cal_date` date NOT NULL,
  `broker` varchar(4) COLLATE utf8mb4_unicode_ci NOT NULL,
  `fof_nav` decimal(22,8) DEFAULT NULL,
  `fof_input_share` decimal(22,8) DEFAULT NULL,
  `fof_output_share` decimal(22,8) DEFAULT NULL,
  `fof_holding_share` decimal(22,8) DEFAULT NULL,
  `fof_holding_cost` decimal(22,8) DEFAULT NULL,
  `fof_holding_unit` decimal(22,8) DEFAULT NULL,
  `fof_holding_profit` decimal(22,8) DEFAULT NULL,
  `fof_holding_profit_rate` decimal(22,8) DEFAULT NULL,
  PRIMARY KEY (`account3_id`,`txn_account_id`,`cal_date`,`broker`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci/*!90000 SHARD_ROW_ID_BITS=4 PRE_SPLIT_REGIONS=4 */
1 row in set (0.00 sec)

info_collecting.py 输出:

$ python info_collecting.py
{‘tidb_log_dir’: ‘{{ deploy_dir }}/log’, ‘dummy’: None, ‘tidb_port’: 4000, ‘tidb_status_port’: 10080, ‘tidb_cert_dir’: ‘{{ deploy_dir }}/conf/ssl’}

系统信息
+--------------------+----------------------------+
|        Host        |          Release           |
+--------------------+----------------------------+
|  prod-tikv4-e005   | 3.10.0-957.21.3.el7.x86_64 |
|  prod-tikv4-e006   | 3.10.0-957.21.3.el7.x86_64 |
|  prod-tikv4-e007   | 3.10.0-957.21.3.el7.x86_64 |
|  prod-tidb4-e002   | 3.10.0-957.21.3.el7.x86_64 |
|  prod-tidb4-e001   | 3.10.0-957.21.3.el7.x86_64 |
|  prod-tipd4-e001   | 3.10.0-957.21.3.el7.x86_64 |
|  prod-tipd4-e003   | 3.10.0-957.21.3.el7.x86_64 |
|  prod-tipd4-e002   | 3.10.0-957.21.3.el7.x86_64 |
|  prod-tikv4-e004   | 3.10.0-957.21.3.el7.x86_64 |
|  prod-tikv4-e001   | 3.10.0-957.21.3.el7.x86_64 |
|  prod-tikv4-e002   | 3.10.0-957.21.3.el7.x86_64 |
|  prod-tikv4-e003   | 3.10.0-957.21.3.el7.x86_64 |
| prod-tispark4-e001 | 3.10.0-957.21.3.el7.x86_64 |
|  prod-tidm4-e001   | 3.10.0-957.21.3.el7.x86_64 |
|  prod-tidm4-e002   | 3.10.0-957.21.3.el7.x86_64 |
+--------------------+----------------------------+
TiDB 集群信息
+--------------------+--------------+------+----+------+
|    TiDB_version    | Clu_replicas | TiDB | PD | TiKV |
+--------------------+--------------+------+----+------+
| 5.7.25-TiDB-v4.0.1 |      3       |  3   | 3  |  7   |
+--------------------+--------------+------+----+------+
集群节点信息
+-------------+-------------+
|   Node_IP   | Server_info |
+-------------+-------------+
|  instance_0 |     tikv    |
|  instance_1 |     tikv    |
|  instance_2 |      pd     |
|  instance_3 |     tikv    |
|  instance_4 |      pd     |
|  instance_5 |      pd     |
|  instance_6 |     tidb    |
|  instance_9 |     tikv    |
|  instance_7 |     tidb    |
| instance_10 |     tikv    |
| instance_11 |     tikv    |
| instance_12 |     tikv    |
|  instance_8 |     tidb    |
+-------------+-------------+
容量 & region 数量
+---------------------+-----------------+--------------+
| Storage_capacity_GB | Storage_uesd_GB | Region_count |
+---------------------+-----------------+--------------+
|       14110.10      |     5883.17     |    503446    |
+---------------------+-----------------+--------------+
QPS
+---------+----------------+-----------------+
| Clu_QPS | Duration_99_MS | Duration_999_MS |
+---------+----------------+-----------------+
| 4809.49 |     735.57     |      960.47     |
+---------+----------------+-----------------+
热点 region 信息
+---------------+----------+-----------+
|     Store     | Hot_read | Hot_write |
+---------------+----------+-----------+
| store-3553218 |    0     |     7     |
| store-3421190 |    7     |     7     |
|    store-1    |    7     |     21    |
|    store-5    |    4     |     13    |
|    store-4    |    3     |     14    |
|    store-6    |    3     |     14    |
| store-3554214 |    4     |     14    |
+---------------+----------+-----------+
磁盘延迟信息
+--------+-------------+-------------+--------------+
| Device |   Instance  | Read_lat_MS | Write_lat_MS |
+--------+-------------+-------------+--------------+
|  vda   | instance_11 |     nan     |     0.17     |
|  vda   | instance_12 |     nan     |     0.14     |
|  vda   | instance_10 |     nan     |     0.14     |
|  vda   |  instance_6 |     nan     |     nan      |
|  vda   |  instance_7 |     nan     |     0.00     |
|  vda   |  instance_4 |     nan     |     nan      |
|  vda   |  instance_5 |     nan     |     0.00     |
|  vda   |  instance_2 |     nan     |     nan      |
|  vda   |  instance_3 |     nan     |     nan      |
|  vda   |  instance_0 |     nan     |     0.00     |
|  vda   |  instance_1 |     nan     |     nan      |
|  vda   |  instance_9 |     nan     |     nan      |
|  vda   |  instance_8 |     nan     |     0.00     |
|  vdb   | instance_11 |     3.43    |     0.97     |
|  vdb   | instance_12 |     4.16    |     0.46     |
|  vdb   | instance_10 |     0.42    |     0.22     |
|  vdb   |  instance_6 |     nan     |     0.31     |
|  vdb   |  instance_7 |     nan     |     0.00     |
|  vdb   |  instance_4 |     nan     |     0.72     |
|  vdb   |  instance_5 |     nan     |     0.27     |
|  vdb   |  instance_2 |     nan     |     0.13     |
|  vdb   |  instance_3 |     2.21    |     0.38     |
|  vdb   |  instance_0 |     0.33    |     0.25     |
|  vdb   |  instance_1 |     0.51    |     0.47     |
|  vdb   |  instance_9 |     2.26    |     0.44     |
|  vdb   |  instance_8 |     nan     |     0.67     |
+--------+-------------+-------------+--------------+

看上面的描述,还是写的速度不符合预期,可以根据文档这里介绍的写流程排查: https://github.com/pingcap/tidb-map/blob/master/maps/performance-map.png

新建了一个测试集群,
3 TiKV: 16C/64G + 1788G NVMe SSD,
3 PD: 4C/8G + 240G PL1 ESSD (13800 IOPS)
1 TiDB: 8C/16G

CREATE TABLE `t` (
  `account3_id` bigint(20) NOT NULL,
  `txn_account_id` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL,
  `cal_date` date NOT NULL,
  `broker` varchar(4) COLLATE utf8mb4_unicode_ci NOT NULL,
  `fof_nav` decimal(22,8) DEFAULT NULL,
  `fof_input_share` decimal(22,8) DEFAULT NULL,
  `fof_output_share` decimal(22,8) DEFAULT NULL,
  `fof_holding_share` decimal(22,8) DEFAULT NULL,
  `fof_holding_cost` decimal(22,8) DEFAULT NULL,
  `fof_holding_unit` decimal(22,8) DEFAULT NULL,
  `fof_holding_profit` decimal(22,8) DEFAULT NULL,
  `fof_holding_profit_rate` decimal(22,8) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

一共 4552347 数据,使用 tispark 读取 parquet 数据后往 tikv 里写入,spark-submit 关键参数:

--driver-memory 2g --driver-cores 2 --executor-memory=32g --executor-cores 8 \
--conf spark.executor.instances=8 --conf spark.tispark.writeThreadPerTask=10 \
--conf spark.tispark.regionSplitNum=16

spark.write().format(“tidb”).option(“bytesPerRegion”, 10485760), 10MB 的 region,从 show table … regions 看,tispark 创建了 60 个 region。

使用 spark 2.4.7 + tispark 2.3.9 以及上述 spark-submit 参数压测,非常稳定在 8w rows/s,从阿里云虚拟机监控、TiDB 自己监控看,机器cpu、线程池 cpu、磁盘 IOPS 都没到瓶颈,对照了上面的 performance map,指标比阈值低很多。 在对 rocksdb 参数做了些改动后,TiDB 监控显示的 write-grpc latency 降低了一半,但是写入性能依然稳如狗,停留在 8w rows/s。

如果并行跑三份 job 写不同表,一共可以到大约 18w rows/s。为啥我跑单独一份 spark job 到不了 10w rows/s 以上呢?

应该是我乌龙了,忘记之前调试问题时把 log4j 日志设成 DEBUG 了。。。

改成 INFO 级别后,默认 tikv 配置可以到 16w rows/s(只算两个 foreachPartition,如果算 tispark 完整过程则为 4.2w rows/s)。乱优化的 tikv 配置可以到 25w rows/s(…, 5w rows/s), 似乎乱优化的还算对头:smile:

:+1: 可以梳理下测试过程,整理出一篇使用实践分享出来哈。